diff --git a/Applications/Applications.cmake b/Applications/Applications.cmake new file mode 100644 index 0000000000000000000000000000000000000000..25c8fe2c2d4f3f78ea1dd4a2b3e6fb33020057a1 --- /dev/null +++ b/Applications/Applications.cmake @@ -0,0 +1,2 @@ +add_subdirectory(Applications/LidDrivenCavity) + diff --git a/Applications/IncludsList.cmake b/Applications/IncludsList.cmake new file mode 100644 index 0000000000000000000000000000000000000000..ce0e9fb545bd648d459f5a1868bd3c748fceeaa3 --- /dev/null +++ b/Applications/IncludsList.cmake @@ -0,0 +1,3 @@ +INCLUDE_DIRECTORIES(${APPS_ROOT}) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/IncludsList.cmake) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/IncludsList.cmake) diff --git a/Applications/LidDrivenCavity/CMakeLists.txt b/Applications/LidDrivenCavity/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2c2df66d397b6277bc0c73c6970222ae49578d55 --- /dev/null +++ b/Applications/LidDrivenCavity/CMakeLists.txt @@ -0,0 +1,25 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +######################################################## +## C++ PROJECT ### +######################################################## +PROJECT(LidDrivenCavity) + +INCLUDE(${APPS_ROOT}/IncludsList.cmake) + +################################################################# +### LOCAL FILES ### +################################################################# +FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp ) + +SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES}) +SOURCE_GROUP(src FILES ${SPECIFIC_FILES}) + +SET(CAB_ADDITIONAL_LINK_LIBRARIES VirtualFluids) + +################################################################# +### CREATE PROJECT ### +################################################################# +CREATE_CAB_PROJECT(LidDrivenCavity BINARY) diff --git a/Applications/LidDrivenCavity/LidDrivenCavity.cpp b/Applications/LidDrivenCavity/LidDrivenCavity.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21d3f7bb70fc2c717b39ffb8bc37da0dad14782c --- /dev/null +++ b/Applications/LidDrivenCavity/LidDrivenCavity.cpp @@ -0,0 +1,244 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LidDrivenCavity.cpp +//! \ingroup Applications +//! \author Konstantin Kutscher +//======================================================================================= + +#include <string> + +#include "VirtualFluids.h" + +using namespace std; + +int main(int argc, char* argv[]) +{ + try + { + ////////////////////////////////////////////////////////////////////////// + // Simulation parameters + ////////////////////////////////////////////////////////////////////////// + + // set your output path here + string path = "./output"; + + const double L = 1.0; + const double Re = 1000.0; + const double velocity = 1.0; + const double dt = 0.5e-3; + const unsigned int nx = 64; + + const double timeStepOut = 1000; + const double timeStepEnd = 25000; + + // Number of OpenMP threads + int numOfThreads = 4; + + ////////////////////////////////////////////////////////////////////////// + + double dx = L / double(nx); + const double velocityLB = velocity * dt / dx; // LB units + const double u = velocityLB / sqrt(2.0); // LB units + const double viscosityLB = nx * velocityLB / Re; // LB unit + + ////////////////////////////////////////////////////////////////////////// + // create grid + ////////////////////////////////////////////////////////////////////////// + // bounding box + double g_minX1 = -0.5; + double g_minX2 = -0.5; + double g_minX3 = -0.5; + + double g_maxX1 = 0.5; + double g_maxX2 = 0.5; + double g_maxX3 = 0.5; + + // NullCommunicator is a place-holder for interprocess communication + SPtr<Communicator> comm = NullCommunicator::getInstance(); + // new grid object + SPtr<Grid3D> grid(new Grid3D(comm)); + // set grid spacing + grid->setDeltaX(dx); + // set block size for three dimensions + int blockSize = nx / 2; + grid->setBlockNX(blockSize,blockSize,blockSize); + + // Create simulation bounding box + SPtr<GbObject3D> gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3)); + GbSystem3D::writeGeoObject(gridCube.get(), path + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); + + UBLOG(logINFO, "Lid Driven Cavity:"); + UBLOG(logINFO, "Domain size = " << nx << " x "<< nx << " x "<< nx); + UBLOG(logINFO, "Block size = " << blockSize << " x "<< blockSize << " x "<< blockSize); + UBLOG(logINFO, "velocity = " << velocity << " m/s"); + UBLOG(logINFO, "velocityLB = " << velocityLB); + UBLOG(logINFO, "viscosityLB = " << viscosityLB); + UBLOG(logINFO, "u = " << u); + UBLOG(logINFO, "Re = " << Re); + UBLOG(logINFO, "dx = " << dx); + UBLOG(logINFO, "dt = " << dt); + UBLOG(logINFO, "Preprocess - start"); + + // Generate block grid + GenBlocksGridVisitor genBlocks(gridCube); + grid->accept(genBlocks); + + // Write block grid to VTK-file + SPtr<CoProcessor> ppblocks(new WriteBlocksCoProcessor(grid, SPtr<UbScheduler>(new UbScheduler(1)), path, WbWriterVtkXmlBinary::getInstance(), comm)); + ppblocks->process(0); + ppblocks.reset(); + + // Create LBM kernel + SPtr<LBMKernel> kernel = SPtr<LBMKernel>(new CumulantK17LBMKernel()); + + ////////////////////////////////////////////////////////////////////////// + // Create boundary conditions (BC) + ////////////////////////////////////////////////////////////////////////// + // Create no-slip BC + SPtr<BCAdapter> noSlipBCAdapter(new NoSlipBCAdapter()); + noSlipBCAdapter->setBcAlgorithm(SPtr<BCAlgorithm>(new NoSlipBCAlgorithm())); + + // Velocity BC + mu::Parser fct; + fct.SetExpr("u"); + fct.DefineConst("u", u); + // Set the same velocity in x and y-direction + SPtr<BCAdapter> velBCAdapter(new VelocityBCAdapter(true, true, false, fct, 0, BCFunction::INFCONST)); + velBCAdapter->setBcAlgorithm(SPtr<BCAlgorithm>(new VelocityBCAlgorithm())); + + // Add velocity boundary condition to visitor. No-slip boundary + BoundaryConditionsBlockVisitor bcVisitor; + bcVisitor.addBC(velBCAdapter); + + // Create boundary conditions processor + SPtr<BCProcessor> bcProc; + bcProc = SPtr<BCProcessor>(new BCProcessor()); + kernel->setBCProcessor(bcProc); + + // Create boundary conditions geometry + GbCuboid3DPtr wallXmin(new GbCuboid3D(g_minX1 - dx, g_minX2 - dx, g_minX3 - dx, g_minX1, g_maxX2 + dx, g_maxX3)); + GbSystem3D::writeGeoObject(wallXmin.get(), path + "/geo/wallXmin", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallXmax(new GbCuboid3D(g_maxX1, g_minX2 - dx, g_minX3 - dx, g_maxX1 + dx, g_maxX2 + dx, g_maxX3)); + GbSystem3D::writeGeoObject(wallXmax.get(), path + "/geo/wallXmax", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallYmin(new GbCuboid3D(g_minX1 - dx, g_minX2 - dx, g_minX3 - dx, g_maxX1 + dx, g_minX2, g_maxX3)); + GbSystem3D::writeGeoObject(wallYmin.get(), path + "/geo/wallYmin", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallYmax(new GbCuboid3D(g_minX1 - dx, g_maxX2, g_minX3 - dx, g_maxX1 + dx, g_maxX2 + dx, g_maxX3)); + GbSystem3D::writeGeoObject(wallYmax.get(), path + "/geo/wallYmax", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallZmin(new GbCuboid3D(g_minX1 - dx, g_minX2 - dx, g_minX3 - dx, g_maxX1 + dx, g_maxX2 + dx, g_minX3)); + GbSystem3D::writeGeoObject(wallZmin.get(), path + "/geo/wallZmin", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallZmax(new GbCuboid3D(g_minX1 - dx, g_minX2 - dx, g_maxX3, g_maxX1 + dx, g_maxX2 + dx, g_maxX3 + dx)); + GbSystem3D::writeGeoObject(wallZmax.get(), path + "/geo/wallZmax", WbWriterVtkXmlASCII::getInstance()); + + // Add boundary conditions to grid generator + SPtr<D3Q27Interactor> wallXminInt(new D3Q27Interactor(wallXmin, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallXmaxInt(new D3Q27Interactor(wallXmax, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallYminInt(new D3Q27Interactor(wallYmin, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallYmaxInt(new D3Q27Interactor(wallYmax, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallZminInt(new D3Q27Interactor(wallZmin, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallZmaxInt(new D3Q27Interactor(wallZmax, grid, velBCAdapter, Interactor3D::SOLID)); + + InteractorsHelper intHelper(grid); + intHelper.addInteractor(wallZmaxInt); + intHelper.addInteractor(wallXminInt); + intHelper.addInteractor(wallXmaxInt); + intHelper.addInteractor(wallZminInt); + intHelper.addInteractor(wallYminInt); + intHelper.addInteractor(wallYmaxInt); + + intHelper.selectBlocks(); + + // Generate grid + SetKernelBlockVisitor kernelVisitor(kernel, viscosityLB); + grid->accept(kernelVisitor); + + intHelper.setBC(); + + // Initialization of distributions + InitDistributionsBlockVisitor initVisitor; + grid->accept(initVisitor); + + // Set connectivity between blocks + SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, viscosityLB); + grid->accept(setConnsVisitor); + + // Create lists of boundary nodes + grid->accept(bcVisitor); + + // Write grid with boundary conditions information to VTK-file + SPtr<UbScheduler> geoSch(new UbScheduler(1)); + WriteBoundaryConditionsCoProcessor ppgeo(grid, geoSch, path, WbWriterVtkXmlBinary::getInstance(), comm); + ppgeo.process(0); + + UBLOG(logINFO, "Preprocess - end"); + + UBLOG(logINFO, "Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()/1e9 << " GB"); + UBLOG(logINFO, "Physical Memory currently used: " << Utilities::getPhysMemUsed()/1e9 << " GB"); + UBLOG(logINFO, "Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()/1e9 << " GB"); + + // Create coprocessor object for writing macroscopic quantities to VTK-file + SPtr<UbScheduler> visSch(new UbScheduler(timeStepOut)); + SPtr<CoProcessor> mqCoProcessor(new WriteMacroscopicQuantitiesCoProcessor(grid, visSch, path, WbWriterVtkXmlBinary::getInstance(), SPtr<LBMUnitConverter>(new LBMUnitConverter(L, velocity, 1.0, nx, velocityLB)), comm)); + mqCoProcessor->process(0); + + // Create coprocessor object for writing NUPS + SPtr<UbScheduler> nupsSch(new UbScheduler(100, 100)); + SPtr<CoProcessor> nupsCoProcessor(new NUPSCounterCoProcessor(grid, nupsSch, numOfThreads, comm)); + + // OpenMP threads control +#ifdef _OPENMP + omp_set_num_threads(numOfThreads); +#endif + // Create simulation + SPtr<Calculator> calculator(new BasicCalculator(grid, visSch, (int)timeStepEnd)); + // Add coprocessors objects to simulation + calculator->addCoProcessor(nupsCoProcessor); + calculator->addCoProcessor(mqCoProcessor); + + ////////////////////////////////////////////////////////////////////////// + // Run simulation + ////////////////////////////////////////////////////////////////////////// + + UBLOG(logINFO, "Simulation-start"); + calculator->calculate(); + UBLOG(logINFO, "Simulation-end"); + } + catch (std::exception& e) + { + cerr << e.what() << endl << flush; + } + catch (std::string& s) + { + cerr << s << endl; + } + catch (...) + { + cerr << "unknown exception" << endl; + } +} + diff --git a/Applications/VirtualFluids.h b/Applications/VirtualFluids.h new file mode 100644 index 0000000000000000000000000000000000000000..1553cebbe6b905d7358636224e7e815f575ac314 --- /dev/null +++ b/Applications/VirtualFluids.h @@ -0,0 +1,142 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VirtualFluids.h +//! \ingroup Applications +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef VirtualFluids_h__ +#define VirtualFluids_h__ + +//VirtualFluids header files + +#ifdef _OPENMP +#include <omp.h> +#endif + +#include <PointerDefinitions.h> + +#include <MuParser/include/muParser.h> + +#include <basics/container/CbArray2D.h> +#include <basics/container/CbArray3D.h> +#include <basics/container/CbArray4D.h> +#include <basics/container/CbVector.h> + +#include <basics/objects/ObObject.h> + +#include <basics/utilities/UbComparators.h> +#include <basics/utilities/UbEqual.h> +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbInfinity.h> +#include <basics/utilities/UbKeys.h> +#include <basics/utilities/UbLimits.h> +#include <basics/utilities/UbLogger.h> +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbObservable.h> +#include <basics/utilities/UbObserver.h> +#include <basics/utilities/UbScheduler.h> +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbTiming.h> +#include <basics/utilities/UbTuple.h> + +#include <basics/writer/WbWriter.h> +#include <basics/writer/WbWriterVtkXmlASCII.h> +#include <basics/writer/WbWriterVtkXmlBinary.h> + +#include <BoundaryConditions/BCArray3D.h> +#include <BoundaryConditions/BCProcessor.h> +#include <BoundaryConditions/BCAlgorithm.h> +#include <BoundaryConditions/BCFunction.h> +#include <BoundaryConditions/BoundaryConditions.h> +#include <BoundaryConditions/BCAdapter.h> +#include <BoundaryConditions/BCProcessor.h> +#include <BoundaryConditions/NoSlipBCAdapter.h> +#include <BoundaryConditions/VelocityBCAdapter.h> +#include <BoundaryConditions/BCAlgorithm.h> +#include <BoundaryConditions/VelocityBCAlgorithm.h> +#include <BoundaryConditions/NoSlipBCAlgorithm.h> + +#include <Connectors/Block3DConnector.h> +#include <Connectors/D3Q27ETFullDirectConnector.h> +#include <Connectors/LocalBlock3DConnector.h> + +#include <Data/D3Q27EsoTwist3DSplittedVector.h> +#include <Data/DataSet3D.h> +#include <Data/DistributionArray3D.h> +#include <Data/EsoTwist3D.h> +#include <Data/EsoTwistD3Q27System.h> + +#include <Grid/Block3D.h> +#include <Grid/Calculator.h> +#include <Grid/BasicCalculator.h> +#include <Grid/Grid3D.h> +#include <Grid/Grid3DSystem.h> + +#include <Interactors/D3Q27Interactor.h> +#include <Interactors/Interactor3D.h> +#include <Interactors/InteractorsHelper.h> + +#include <CoProcessors/WriteBlocksCoProcessor.h> +#include <CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h> +#include <CoProcessors/WriteBoundaryConditionsCoProcessor.h> +#include <CoProcessors/NUPSCounterCoProcessor.h> +#include <CoProcessors/CoProcessor.h> + +#include <LBM/D3Q27System.h> +#include <LBM/LBMKernel.h> +#include <LBM/ILBMKernel.h> +#include <LBM/CumulantK17LBMKernel.h> +#include <LBM/LBMSystem.h> +#include <LBM/LBMUnitConverter.h> + +#include <geometry3d/CoordinateTransformation3D.h> +#include <geometry3d/GbCuboid3D.h> +#include <geometry3d/GbLine3D.h> +#include <geometry3d/GbObject3D.h> +#include <geometry3d/GbPoint3D.h> +#include <geometry3d/GbPolygon3D.h> +#include <geometry3d/GbSystem3D.h> +#include <geometry3d/GbTriangle3D.h> +#include <geometry3d/GbVector3D.h> + +#include <Parallel/Communicator.h> +#include <Parallel/NullCommunicator.h> + +#include <Utilities/MemoryUtil.h> + +#include <Visitors/Block3DVisitor.h> +#include <Visitors/InitDistributionsBlockVisitor.h> +#include <Visitors/SetConnectorsBlockVisitor.h> +#include <Visitors/GenBlocksGridVisitor.h> +#include <Visitors/Grid3DVisitor.h> +#include <Visitors/SetKernelBlockVisitor.h> +#include <Visitors/BoundaryConditionsBlockVisitor.h> + +#endif // VirtualFluids_h__ diff --git a/CMake/CMakeCABMacros.txt b/CMake/CMakeCABMacros.txt new file mode 100644 index 0000000000000000000000000000000000000000..d7a6601e94905869a7eacf6ffa369811b664e218 --- /dev/null +++ b/CMake/CMakeCABMacros.txt @@ -0,0 +1,317 @@ +############################################################### +# Aktivieren von IF(ARG)...ELSE()...ENDIF() in CMake +############################################################### +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 1) + +############################################################################################################### +## Flags ruecksetzen +############################################################################################################### +SET(CAB_ADDTIONAL_COMPILER_FLAGS) +#because of the fact that CMake does not support COMPILER_FLAGS_<CONFIG> right know we cannot use these options +#SET(CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG) +#SET(CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE) + +SET(CAB_ADDITIONAL_LINK_FLAGS) +SET(CAB_ADDITIONAL_LINK_FLAGS_DEBUG) +SET(CAB_ADDITIONAL_LINK_FLAGS_RELEASE) + +SET(CAB_ADDITIONAL_LINK_LIBRARIES) + + +############################################################### +# SOURCE_DIR variable wird beim einbinden automatisch gesetzt - ebenso das include dir!!! +# SOURCE_DIR wird dem Projekt als Standardincludepfad hinzugefuegt +############################################################### +#CMakeCABMacros.txt liegt direkt im source-Ordner -> pfad == SOURCE_ROOT +GET_FILENAME_COMPONENT( SOURCE_ROOT ${CMAKE_CURRENT_LIST_FILE} PATH) +STRING(REGEX REPLACE "(.*)/CMake" "\\1" SOURCE_ROOT "${SOURCE_ROOT}" ) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}) +LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DSOURCE_ROOT=${SOURCE_ROOT} ) + +############################################################### +# hostename ermitteln -> CAB_MACHINE +############################################################### +IF(NOT CAB_MACHINE) + SET(CAB_MACHINE $ENV{CAB_MACHINE}) + + IF( CAB_MACHINE ) + STRING(TOUPPER "${CAB_MACHINE}" CAB_MACHINE) + ELSE() + EXECUTE_PROCESS( COMMAND hostname OUTPUT_VARIABLE CAB_MACHINE) + STRING(REGEX REPLACE "[ ]*([A-Za-z0-9]+).*[\\\\n]*" "\\1" CAB_MACHINE "${CAB_MACHINE}" ) + STRING(TOUPPER "${CAB_MACHINE}" CAB_MACHINE) + ENDIF() +ENDIF() + + +############################################################### +# WITH_SUBFOLDERS_FOR_SG erstellen, wenn noch nicht vorhanden +# ist diese auf true wird bei SOURCE_GROUP in VS unterordner erzeugt +# dies funktioniert erst ab CMake-2.5 vernuenftig +############################################################### +IF(NOT WITH_SUBFOLDERS_FOR_SG) + SET(WITH_SUBFOLDERS_FOR_SG FALSE) +ENDIF() + + +############################################################################ +############################################################################ +## M A C R O S ## +## M A C R O S ## +## M A C R O S ## +############################################################################ +############################################################################ +# externe (ACHTUNG: die darin enthaltenen benoetigen teils noch macros die +# hier im Anschluss folgen +INCLUDE("${SOURCE_ROOT}/CMake/CMakeSetCompilerFlags.txt") +INCLUDE("${SOURCE_ROOT}/CMake/CMakeCompilerMacros.txt") + +################################################################ +### ADD_TARGET_PROPERTIES ### +################################################################ +MACRO(ADD_TARGET_PROPERTIES target property) + + SET(property_values ${ARGN}) + + # vorhandene properties holen + GET_TARGET_PROPERTY(TEMP_VAR ${target} ${property}) + IF(TEMP_VAR) + LIST(APPEND property_values ${TEMP_VAR}) + ENDIF() + + #STRING(REGEX REPLACE ";" " " property_values ${property_values}) + # doppelte Eintraege loeschen + SEPARATE_ARGUMENTS(property_values) + LIST(REMOVE_DUPLICATES property_values) + + #aus Liste wieder einen String basteln (geht nich tmit regex replace...) + SET(new_property_values) + FOREACH(p ${property_values}) + SET(new_property_values "${p} ${new_property_values}") + ENDFOREACH() + + #property setzen + SET_TARGET_PROPERTIES(${target} PROPERTIES ${property} ${new_property_values}) + + #GET_TARGET_PROPERTY(TEMP_VAR ${target} ${property}) + #MESSAGE("danach ${target} ${property} ${TEMP_VAR}") + +ENDMACRO(ADD_TARGET_PROPERTIES target property) + + +################################################################ +### CHECK_FOR_VARIABLE ### +### checks for a variable (also env-variables) +### if not found -> error-message!!! +### always: cache-entry update +################################################################ +MACRO(CHECK_FOR_VARIABLE var) + #check ob evtl enviromentvariable gesetzt + IF(NOT DEFINED ${var}) #true if ${var} NOT: empty, 0, N, NO, OFF, FALSE, NOTFOUND, or <variable>-NOTFOUND + SET(${var} $ENV{${var}}) + ENDIF() + + IF(NOT DEFINED ${var}) + SET(${var} "${var}-NOTFOUND" CACHE STRING "${ARGN}" FORCE) + ENDIF(NOT DEFINED ${var}) + + IF(${var} MATCHES ".*-NOTFOUND") + MESSAGE(FATAL_ERROR "CHECK_FOR_VARIABLE - error - set ${var}") + ENDIF() + + SET(${var} ${${var}} CACHE STRING "${ARGN}" FORCE) +ENDMACRO(CHECK_FOR_VARIABLE var) + + +############################################################### +### CAB_SOURCE_GROUP( sourceGroupName ) ### +### creates a source group for the given folder and files. ### +############################################################### +MACRO(CAB_SOURCE_GROUP sourceGroupName) + SET(tempSourceGroupName ${sourceGroupName}) + IF(WITH_SUBFOLDERS_FOR_SG) + STRING(REGEX REPLACE "/" "\\\\" tempSourceGroupName ${tempSourceGroupName}) + ENDIF() + SOURCE_GROUP(${tempSourceGroupName} FILES ${ARGN}) +ENDMACRO(CAB_SOURCE_GROUP) + +################################################################################# +### COLLECT_PACKAGE_DATA( currentDir sourceGroupName outFiles) ### +### collects header and cpp file of current dir and add them to "outfiles" ### +### all files will be put to the SOURCE_GROUP-folder "sourceGroupName" ### +### and this one will be with subfolders if WITH_SUBFOLDERS_FOR_SG==YES ### +################################################################################# +MACRO(COLLECT_PACKAGE_DATA currentDir sourceGroupName outFiles) + FILE( GLOB _HEADER_FILES ${currentDir}/*.h ) + FILE( GLOB _CPP_FILES ${currentDir}/*.cpp ) + FILE( GLOB _CXX_FILES ${currentDir}/*.cxx ) + FILE( GLOB _HPP_FILES ${currentDir}/*.hpp ) + FILE( GLOB _C_FILES ${currentDir}/*.c ) + + IF(CAB_PACKAGE_DEFINTIONS) + SET_SOURCE_FILES_PROPERTIES( ${CPP_FILES} PROPERTIES COMPILE_FLAGS ${CAB_PACKAGE_DEFINTIONS} ) + ENDIF(CAB_PACKAGE_DEFINTIONS) + + CAB_SOURCE_GROUP( ${sourceGroupName} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} ) + + #SET( ${outFiles} ${${outFiles}} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} ) + LIST(APPEND ${outFiles} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} ) +ENDMACRO(COLLECT_PACKAGE_DATA currentDir sourceGroupName sourceGroupWithSubfolders outFiles) + + +################################################################################################################## +### COLLECT_PACKAGE_DATA_WITH_OPTION( currentDir outFiles [outOption] [outSourceGroupName]) ### +### collects header and cpp file of current dir and add them to "outfiles" ### +### all files will be put to the SOURCE_GROUP-folder "sourceGroupName" ### +### and this one will be with subfolders if WITH_SUBFOLDERS_FOR_SG==YES ### +################################################################################################################## +MACRO(COLLECT_PACKAGE_DATA_WITH_OPTION currentDir outFiles) + STRING(REGEX REPLACE "(.*)/source/(.*)" "\\2" SOURCE_GROUP_NAME "${currentDir}") + STRING(REGEX REPLACE "/" "_" OPTION_LABEL "${SOURCE_GROUP_NAME}") + STRING(REGEX REPLACE ":" "" OPTION_LABEL "${OPTION_LABEL}") + STRING(TOUPPER ${OPTION_LABEL} OPTION_LABEL) + + SET(OPTION_LABEL "BUILD_${OPTION_LABEL}") + OPTION(${OPTION_LABEL} "${currentDir}" ON) + + IF( ${OPTION_LABEL} ) + COLLECT_PACKAGE_DATA( ${currentDir} ${SOURCE_GROUP_NAME} ${outFiles}) + ENDIF(${OPTION_LABEL}) + + IF(${ARGC} GREATER 2) + SET( ${ARGV2} ${OPTION_LABEL} ) + ENDIF() + + IF(${ARGC} GREATER 3) + SET( ${ARGV3} ${SOURCE_GROUP_NAME} ) + ENDIF() + +ENDMACRO(COLLECT_PACKAGE_DATA_WITH_OPTION currentDir outFiles) + + +################################################################# +### GET_DIRECTORY_FROM_ENV( var env_var [CACHE] [STRING]) ### +### if enn_var exists the value with corrected slashes will ### +### be stored in var. ### +### if optional CACHE is activated the var will be stored as ### +### cache variable. optional you can use a status bar string ### +################################################################# +MACRO(GET_DIRECTORY_FROM_ENV var env_var) + SET(${var} $ENV{${env_var}}) + IF(${var}) + STRING(REGEX REPLACE "\\\\" "/" ${var} ${${var}}) # "\" --> "/" + IF(${ARGC} EQUAL 3 AND ${ARGV2} MATCHES "CACHE") + SET(${var} ${${var}} CACHE PATH "" FORCE) + ENDIF(${ARGC} EQUAL 3 AND ${ARGV2} MATCHES "CACHE") + IF(${ARGC} EQUAL 4 AND ${ARGV2} MATCHES "CACHE") + SET(${var} ${${var}} CACHE PATH "${ARGV3}" FORCE) + ENDIF(${ARGC} EQUAL 4 AND ${ARGV2} MATCHES "CACHE") + ENDIF(${var}) +ENDMACRO(GET_DIRECTORY_FROM_ENV var env_var) + +################################################################# +### GET_DIRECTORY_FROM_VAR( var [CACHE] [STRING]) ### +### if optional CACHE is activated the var will be stored as ### +### cache variable. optional you can use a status bar string ### +################################################################# +MACRO(GET_DIRECTORY_FROM_VAR var ) + IF(${var}) + STRING(REGEX REPLACE "\\\\" "/" ${var} ${${var}}) # "\" --> "/" + IF(${ARGC} EQUAL 2 AND ${ARGV1} MATCHES "CACHE") + SET(${var} ${${var}} CACHE PATH "" FORCE) + ENDIF(${ARGC} EQUAL 2 AND ${ARGV1} MATCHES "CACHE") + IF(${ARGC} EQUAL 3 AND ${ARGV1} MATCHES "CACHE") + SET(${var} ${${var}} CACHE PATH "${ARGV2}" FORCE) + ENDIF(${ARGC} EQUAL 3 AND ${ARGV1} MATCHES "CACHE") + ENDIF(${var}) +ENDMACRO(GET_DIRECTORY_FROM_VAR var env_var) + + +################################################################# +### FINAL MACROS TO GENERATE PROJECT FILES ### +### project_name: name of the project ### +### build_type: BINARY | SHARED | STATIC ### +### optinal: prefix +################################################################# +MACRO(CREATE_CAB_PROJECT project_name build_type) + + MESSAGE(STATUS "configuring ${project_name} (type=${build_type})...") + + ################################################################# + ### OS DEFINES ### + ################################################################# + IF(WIN32) + LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__WIN__) + ELSEIF(APPLE) + LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__) + ELSEIF(UNIX) + LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__) + ENDIF() + + ################################################################# + ### ADDITIONAL_MAKE_CLEAN_FILES ### + ################################################################# + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_FILES}") + + ################################################################# + ### EXCECUTABLE ### + ################################################################# + IF(${build_type} MATCHES BINARY) + ADD_EXECUTABLE(${project_name} ${ALL_SOURCES} ) + ELSEIF(${build_type} MATCHES SHARED) + ADD_LIBRARY(${project_name} SHARED ${ALL_SOURCES} ) + ELSEIF(${build_type} MATCHES STATIC) + ADD_LIBRARY(${project_name} STATIC ${ALL_SOURCES} ) + ELSE() + MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC") + ENDIF() + + ################################################################# + ### ADDITIONAL LINK LIBRARIES ### + ################################################################# + IF(CAB_ADDITIONAL_LINK_LIBRARIES) + TARGET_LINK_LIBRARIES(${project_name} ${CAB_ADDITIONAL_LINK_LIBRARIES}) + ENDIF() + + ################################################################# + ### COMPILER Flags ### + ################################################################# + ADD_COMPILER_FLAGS_TO_PROJECT(${CAB_COMPILER} ${project_name} "CXX" ${build_type}) + MESSAGE(STATUS "compiler flags for compiler ${CAB_COMPILER} on machine ${CAB_MACHINE} for project ${project_name} (${build_type}) have been configured") + + IF(CAB_ADDTIONAL_COMPILER_FLAGS) + ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_ADDTIONAL_COMPILER_FLAGS}) + ENDIF() + IF(CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG) + MESSAGE(FATAL_ERROR "COMPILE_FLAGS_DEBUG_<CONFIG> not supported by cmake yet :-(") + ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_DEBUG ${CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG}) + ENDIF() + IF(CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE) + MESSAGE(FATAL_ERROR "COMPILE_FLAGS_<CONFIG> not supported by cmake yet :-(") + ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_RELEASE ${CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE}) + ENDIF() + + ################################################################# + ### ADDITIONAL LINK PROPERTIES ### + ################################################################# + IF(CAB_ADDITIONAL_LINK_FLAGS) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS}) + ENDIF() + IF(CAB_ADDITIONAL_LINK_FLAGS_DEBUG) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS_DEBUG ${CAB_ADDITIONAL_LINK_FLAGS_DEBUG}) + ENDIF() + IF(CAB_ADDITIONAL_LINK_FLAGS_RELEASE) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS_RELEASE ${CAB_ADDITIONAL_LINK_FLAGS_RELEASE}) + ENDIF() + + SET(project_name ${project_name} CACHE STRING "name of binary") + + MESSAGE(STATUS "configuring ${project_name} (type=${build_type})... done") + +ENDMACRO(CREATE_CAB_PROJECT project_name build_type) + +################################################################# +# ALLGEMEINGUELTIGER STUFF +# CAB_COMPILER setzen und machinespecific configfile laden +############################################################### +SET_CAB_COMPILER() diff --git a/CMake/CMakeCompilerMacros.txt b/CMake/CMakeCompilerMacros.txt new file mode 100644 index 0000000000000000000000000000000000000000..68d4ee4e5a8ab1ab8611d32d90a322f18e28e9d8 --- /dev/null +++ b/CMake/CMakeCompilerMacros.txt @@ -0,0 +1,384 @@ +############################################################### +# Aktivieren von ELSIF in CMake +############################################################### +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 1) + +############################################################### +# IS_64BIT_SYSTEM (check put if OS is 64 bit compatible) +############################################################### +MACRO(IS_64BIT_SYSTEM is64BitOutVar) + + SET(${is64BitOutVar} FALSE) + + IF(APPLE) + EXEC_PROGRAM( arch + ARGS -x86_64 echo "64bit" + OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 ) + IF(${CAB_SYSTEM_INFO_1} MATCHES "64bit") + SET(${is64BitOutVar} TRUE) + ENDIF() + + ELSEIF(UNIX) + + EXEC_PROGRAM( uname + ARGS -m + OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 ) + + STRING(REGEX MATCH "x86_64" CAB_SYSTEM_INFO_1 ${CAB_SYSTEM_INFO_1}) + + + EXEC_PROGRAM( getconf + ARGS -a | grep -i LONG_BIT + OUTPUT_VARIABLE CAB_SYSTEM_INFO_2 ) + + STRING(REGEX MATCH "64" CAB_SYSTEM_INFO_2 ${CAB_SYSTEM_INFO_2}) + + IF(CAB_SYSTEM_INFO_1 STREQUAL "x86_64" AND CAB_SYSTEM_INFO_2 STREQUAL "64") + SET(${is64BitOutVar} TRUE) + ENDIF() + + ELSEIF(WIN32) + + MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)...(this may take a few moments)") + EXEC_PROGRAM( SystemInfo OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 ) + + STRING(REGEX MATCH "x64-based PC" CAB_SYSTEM_INFO_1 ${CAB_SYSTEM_INFO_1}) + + IF(CAB_SYSTEM_INFO_1 MATCHES "x64-based PC") + SET(${is64BitOutVar} TRUE) + MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)... done (-> 64 Bit)") + ELSE() + MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)... done (-> 32 Bit)") + ENDIF() + + ELSE() + MESSAGE(FATAL_ERROR "IS_64BIT_SYSTEM: unknown OS") + ENDIF() + +ENDMACRO(IS_64BIT_SYSTEM is64BitOutVar) + + +############################################################### +### SET_CAB_COMPILER ### +### Macro sets CAB_COMPILER variable if not set ### +### for msvc: CMake Variables are used ### +### for intel,gcc: --version call is evaluated ### +############################################################### +MACRO(SET_CAB_COMPILER) + IF(NOT CMAKE_CXX_COMPILER) + MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called") + ELSE() + IF(NOT CAB_COMPILER) + IF(MSVC) + IF(CMAKE_CL_64) + SET( CAB_COMPILER "msvc19_64" ) + ELSE() + SET( CAB_COMPILER "msvc19_32" ) + ENDIF() + #ELSEIF(APPLE) + ELSEIF("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + SET( CAB_COMPILER "clang" ) + ELSE() + EXEC_PROGRAM( ${CMAKE_CXX_COMPILER} + ARGS --version + OUTPUT_VARIABLE CAB_COMPILER_INFO ) + + STRING(REGEX REPLACE ".* \\((.*)\\) ([0-9]*)\\.([0-9]*)[\\. ]([0-9]*).*" "\\1" CAB_COMPILER_NAME ${CAB_COMPILER_INFO}) + STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\1" CAB_COMPILER_VERSION_MAJOR ${CAB_COMPILER_INFO}) + STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\2" CAB_COMPILER_VERSION_MINOR ${CAB_COMPILER_INFO}) + STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\3" CAB_COMPILER_VERSION_PATCH ${CAB_COMPILER_INFO}) + + STRING(TOLOWER ${CAB_COMPILER_NAME} CAB_COMPILER_NAME) + + IF(CMAKE_COMPILER_IS_GNUCXX) + SET(CAB_COMPILER_NAME "gcc") + SET(USE_GCC ON) + ENDIF() + + SET(CAB_COMPILER "${CAB_COMPILER_NAME}${CAB_COMPILER_VERSION_MAJOR}${CAB_COMPILER_VERSION_MINOR}") + ENDIF() + ENDIF() + + SET(CAB_COMPILER ${CAB_COMPILER} CACHE STRING "compiler") + ENDIF() + +ENDMACRO(SET_CAB_COMPILER) + +################################################################ +### CHECK_FOR_VARIABLE ### +### checks for a variable (also env-variables) +### if not found -> error-message!!! +### always: cache-entry update +################################################################ +MACRO(CHECK_FOR_VARIABLE var) + #check ob evtl enviromentvariable gesetzt + IF(NOT ${var}) #true if ${var} NOT: empty, 0, N, NO, OFF, FALSE, NOTFOUND, or <variable>-NOTFOUND + SET(${var} $ENV{${var}}) + ENDIF() + + IF(NOT DEFINED ${var}) + SET(${var} "${var}-NOTFOUND" CACHE STRING "${ARGN}" FORCE) + ENDIF(NOT DEFINED ${var}) + + IF(NOT ${var}) + MESSAGE(FATAL_ERROR "CHECK_FOR_VARIABLE - error - set ${var}") + ENDIF() + +SET(${var} ${${var}} CACHE STRING "${ARGN}" FORCE) +ENDMACRO(CHECK_FOR_VARIABLE var) + + +################################################################# +### ADD_CXX_FLAGS(flags) ### +### flags will be added to CMAKE_CXX_FLAGS ### +################################################################# +MACRO(ADD_CXX_FLAGS) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) +ENDMACRO(ADD_CXX_FLAGS) + +################################################################# +### ADD_CXX_FLAGS_IF(option flags) ### +### flags will be added to CMAKE_CXX_FLAGS if option exists ### +################################################################# +MACRO(ADD_CXX_FLAGS_IF condition) + IF(${condition}) + ADD_CXX_FLAGS(${ARGN}) + ENDIF(${condition}) +ENDMACRO(ADD_CXX_FLAGS_IF) + +################################################################# +### REMOVE_CXX_FLAGS(flags) ### +### flags will be removed from CMAKE_CXX_FLAGS ### +################################################################# +MACRO(REMOVE_CXX_FLAGS) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) +ENDMACRO(REMOVE_CXX_FLAGS) + +##################################################################### +### REMOVE_CXX_FLAGS(option flags) ### +### flags will be removed from CMAKE_CXX_FLAGS if option exists ### +##################################################################### +MACRO(REMOVE_CXX_FLAGS_IF condition) + IF(${condition}) + REMOVE_CXX_FLAGS(${ARGN}) + ENDIF(${condition}) +ENDMACRO(REMOVE_CXX_FLAGS_IF) + +################################################################# +### ADD_CXX_BUILDTYPE_FLAGS(buildtype flags) ### +### flags will be added to CMAKE_CXX_BUILDTYPE_FLAGS ### +################################################################# +MACRO(ADD_CXX_BUILDTYPE_FLAGS buildtype) + IF(CMAKE_CXX_FLAGS_${buildtype}) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}") + STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}") + SET(CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}} ${option}" CACHE STRING "common C++ build flags for ${buildtype}" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) + ENDIF(CMAKE_CXX_FLAGS_${buildtype}) +ENDMACRO(ADD_CXX_BUILDTYPE_FLAGS) + +######################################################################### +### ADD_CXX_BUILDTYPE_FLAGS(buildtype option flags) ### +### flags will be added to CMAKE_CXX_BUILDTYPE_FLAGS if option exists ### +######################################################################### +MACRO(ADD_CXX_BUILDTYPE_FLAGS_IF buildtype condition) + IF(${condition}) + ADD_CXX_BUILDTYPE_FLAGS(${buildtype} ${ARGN}) + ENDIF(${condition}) +ENDMACRO(ADD_CXX_BUILDTYPE_FLAGS_IF) + +################################################################# +### REMOVE_CXX_BUILDTYPE_FLAGS(buildtype flags) ### +### flags will be removed from CMAKE_CXX_FLAGS ### +################################################################# +MACRO(REMOVE_CXX_BUILDTYPE_FLAGS buildtype) + IF(CMAKE_CXX_FLAGS_${buildtype}) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}") + STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}") + SET(CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}" + CACHE STRING "C++ build flags for ${buildtype} configuration" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) + ENDIF(CMAKE_CXX_FLAGS_${buildtype}) +ENDMACRO(REMOVE_CXX_BUILDTYPE_FLAGS) + +##################################################################### +### REMOVE_CXX_BUILDTYPE_FLAGS_IF(buildtype option flags) ### +### flags will be removed from CMAKE_CXX_FLAGS if option exists ### +##################################################################### +MACRO(REMOVE_CXX_BUILDTYPE_FLAGS_IF condition) + IF(${condition}) + REMOVE_CXX_BUILDTYPE_FLAGS(${buildtype} ${ARGN}) + ENDIF(${condition}) +ENDMACRO(REMOVE_CXX_BUILDTYPE_FLAGS_IF) + +##################################################################### +### SET_CXX_COMPILER( compiler) ### +### flags will be removed from CMAKE_CXX_FLAGS if option exists ### +##################################################################### +#MACRO(SET_CXX_COMPILER compiler) +# INCLUDE (CMakeForceCompiler) +# SET(CMAKE_SYSTEM_NAME Generic) +# CMAKE_FORCE_CXX_COMPILER (${compiler} "set by user") +# SET(CMAKE_CXX_COMPILER ${compiler} CACHE STRING "C++ compiler" FORCE) +#ENDMACRO(SET_CXX_COMPILER) + +################################################################# +### ADD_C_FLAGS(flags) ### +### flags will be added to CMAKE_C_FLAGS ### +################################################################# +MACRO(ADD_C_FLAGS) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) +ENDMACRO(ADD_C_FLAGS) + +################################################################# +### ADD_C_FLAGS(option flags) ### +### flags will be added to CMAKE_C_FLAGS if option exists ### +################################################################# +MACRO(ADD_C_FLAGS_IF condition) + IF(${condition}) + ADD_C_FLAGS(${ARGN}) + ENDIF(${condition}) +ENDMACRO(ADD_C_FLAGS_IF) + +################################################################# +### REMOVE_C_FLAGS(flags) ### +### flags will be removed from CMAKE_C_FLAGS ### +################################################################# +MACRO(REMOVE_C_FLAGS) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) +ENDMACRO(REMOVE_C_FLAGS) + +##################################################################### +### REMOVE_C_FLAGS(option flags) ### +### flags will be removed from CMAKE_C_FLAGS if option exists ### +##################################################################### +MACRO(REMOVE_C_FLAGS_IF condition) + IF(${condition}) + REMOVE_C_FLAGS(${ARGN}) + ENDIF(${condition}) +ENDMACRO(REMOVE_C_FLAGS_IF) + +################################################################# +### ADD_C_BUILDTYPE_FLAGS(buildtype flags) ### +### flags will be added to CMAKE_C_BUILDTYPE_FLAGS ### +################################################################# +MACRO(ADD_C_BUILDTYPE_FLAGS buildtype) + IF(CMAKE_C_FLAGS_${buildtype}) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}") + STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}") + SET(CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}} ${option}" CACHE STRING "common C++ build flags for ${buildtype}" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) + ENDIF(CMAKE_C_FLAGS_${buildtype}) +ENDMACRO(ADD_C_BUILDTYPE_FLAGS) + +######################################################################### +### ADD_C_BUILDTYPE_FLAGS(buildtype option flags) ### +### flags will be added to CMAKE_C_BUILDTYPE_FLAGS if option exists ### +######################################################################### +MACRO(ADD_C_BUILDTYPE_FLAGS_IF buildtype condition) + IF(${condition}) + ADD_C_BUILDTYPE_FLAGS(${buildtype} ${ARGN}) + ENDIF(${condition}) +ENDMACRO(ADD_C_BUILDTYPE_FLAGS_IF) + +################################################################# +### REMOVE_C_BUILDTYPE_FLAGS(buildtype flags) ### +### flags will be removed from CMAKE_C_FLAGS ### +################################################################# +MACRO(REMOVE_C_BUILDTYPE_FLAGS buildtype) + IF(CMAKE_C_FLAGS_${buildtype}) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}") + STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}") + SET(CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}" + CACHE STRING "C++ build flags for ${buildtype} configuration" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) + ENDIF(CMAKE_C_FLAGS_${buildtype}) +ENDMACRO(REMOVE_C_BUILDTYPE_FLAGS) + +##################################################################### +### REMOVE_C_BUILDTYPE_FLAGS_IF(buildtype option flags) ### +### flags will be removed from CMAKE_C_FLAGS if option exists ### +##################################################################### +MACRO(REMOVE_C_BUILDTYPE_FLAGS_IF condition) + IF(${condition}) + REMOVE_C_BUILDTYPE_FLAGS(${buildtype} ${ARGN}) + ENDIF(${condition}) +ENDMACRO(REMOVE_C_BUILDTYPE_FLAGS_IF) + +##################################################################### +### SET_C_COMPILER( compiler) ### +### flags will be removed from CMAKE_C_FLAGS if option exists ### +##################################################################### +MACRO(SET_C_COMPILER compiler) + INCLUDE (CMakeForceCompiler) + SET(CMAKE_SYSTEM_NAME Generic) + CMAKE_FORCE_C_COMPILER (${compiler} "set by user") + SET(CMAKE_C_COMPILER ${compiler} CACHE STRING "C compiler" FORCE) +ENDMACRO(SET_C_COMPILER) + +################################################################# +### ADD_EXE_LINKER_FLAGS(flags) ### +### flags will be added to CMAKE_EXE_LINKER_FLAGS ### +################################################################# +MACRO(ADD_EXE_LINKER_FLAGS) + FOREACH(arg ${ARGN}) + SET(TMP ${arg}) #elsewise the Seperate command doesn't work) + SEPARATE_ARGUMENTS(TMP) + FOREACH(option ${TMP}) + STRING(REGEX REPLACE " ${option}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + STRING(REGEX REPLACE "${option}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE) + ENDFOREACH(option ${TMP}) + ENDFOREACH(arg ${ARGN}) +ENDMACRO(ADD_EXE_LINKER_FLAGS) + diff --git a/CMake/CMakeSetCompilerFlags.txt b/CMake/CMakeSetCompilerFlags.txt new file mode 100644 index 0000000000000000000000000000000000000000..fbee7836f0694a9c96004a024f81bec3c68e3414 --- /dev/null +++ b/CMake/CMakeSetCompilerFlags.txt @@ -0,0 +1,139 @@ +################################################################ +### SET_COMPILER_SPECIFIC_FLAGS ### +### determines compiler flags variabels ### +### compiler_type: e.g. msvc9_x64 ### +### build_type : BINARY, STATIC, SHARED ### +################################################################ +MACRO(SET_COMPILER_SPECIFIC_FLAGS compiler_type build_type) + IF(NOT CMAKE_CXX_COMPILER) + MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called") + ENDIF() + + OPTION(USE_OPENMP "activate open" ON) + + IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + SET(USE_OPENMP OFF) + ENDIF() + + ############################################################################################################### + ## Flags ruecksetzen + ############################################################################################################### + SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS "") + SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG "") + SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE "") + + SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "") + SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG "") + SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "") + + SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "") + SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS_DEBUG "") + SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS_RELEASE "") + + ############################################################################################################### + ## ggf. spezielles compiler flag file lesen + ############################################################################################################### + IF( SPECIFIC_COMPILER_FLAG_FILE ) + INCLUDE( ${SPECIFIC_COMPILER_FLAG_FILE}) + ############################################################################################################### + ## standard compiler flags + ############################################################################################################### + ELSEIF( EXISTS "${SOURCE_ROOT}/CMake/compilerflags/${CAB_COMPILER}.cmake" ) + INCLUDE( ${SOURCE_ROOT}/CMake/compilerflags/${CAB_COMPILER}.cmake) + ############################################################################################################### + ## unknown compiler + ############################################################################################################### + ELSE() + #MESSAGE(FATAL_ERROR "CAB_COMPILER=${CAB_COMPILER} seems to be a not supported compiler") + MESSAGE(WARNING "CAB_COMPILER=${CAB_COMPILER} seems to be a not supported compiler; set to generic") + SET(CAB_COMPILER "gccGeneric") + INCLUDE( ${SOURCE_ROOT}/CMake/compilerflags/${CAB_COMPILER}.cmake) + ENDIF() + + + ############################################################################################################### + #64 Bit compilation?? + ############################################################################################################### + IF(NOT DEFINED USE_64BIT_COMPILER_OPTIONS) + IF(MSVC AND NOT CMAKE_CL_64) + SET(OPTION64 OFF) + ELSEIF(MSVC AND CMAKE_CL_64) + SET(OPTION64 ON) + ELSE() + IS_64BIT_SYSTEM( IS64BITSYSTEM ) + IF(IS64BITSYSTEM STREQUAL "TRUE") + SET(OPTION64 ON) + ELSE() + SET(OPTION64 OFF) + ENDIF() + ENDIF() + ENDIF() + + OPTION(USE_64BIT_COMPILER_OPTIONS "set 64 bit compiler flags" ${OPTION64}) + + ############################################################################################################### + # set flags + ############################################################################################################### +IF(USE_64BIT_COMPILER_OPTIONS) + SET_COMPILER_SPECIFIC_FLAGS_INTERN( ${build_type} 1) +else() + SET_COMPILER_SPECIFIC_FLAGS_INTERN( ${build_type} 0) +endif() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS compiler_type build_type) + +################################################################ +### ADD_COMPILER_FLAGS_TO_PROJECT ### +### adds COMPILER_FLGAS TO project ### +### project_language: CXX , C ### +################################################################ +MACRO(ADD_COMPILER_FLAGS_TO_PROJECT compiler_type project_name project_language build_type) + + IF(NOT ${project_language} MATCHES "C") + IF(NOT ${project_language} MATCHES "CXX") + MESSAGE(FATAL_ERROR "project_language must be CXX or C") + ENDIF() + ENDIF() + + ################################################################ + # SET_COMPILER_SPECIFIC_FLAGS + ################################################################ + SET_COMPILER_SPECIFIC_FLAGS( ${compiler_type} ${build_type} ) + + #workaround für itanium processoren + IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ia64") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS -D_M_IA64) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS -D_M_IA64) + ENDIF() + + ################################################################ + # LINKER PROPS + ################################################################ + IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS}) + ENDIF() + IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG}) + ENDIF() + IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE) + ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE}) + ENDIF() + + ################################################################ + # COMPILER FLAGS + ################################################################ + IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS) + ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS}) + ENDIF() + IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_DEBUG) + MESSAGE(STATUS "ADD_COMPILER_FLAGS_TO_PROJECT: sorry, a long as CMake has no support for COMPILE_FLAGS_<CONFIG> -> DEBUG flags are neglected") + #ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_DEBUG ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_DEBUG}) + ENDIF() + IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE) + MESSAGE(STATUS "ADD_COMPILER_FLAGS_TO_PROJECT: sorry, a long as CMake has no support for COMPILE_FLAGS_<CONFIG> -> RELEASE flags are set for RELEASE AND DEBUG") + ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE}) + #ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_RELEASE ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE}) + ENDIF() + + +ENDMACRO(ADD_COMPILER_FLAGS_TO_PROJECT compiler_type project_name project_language build_type) \ No newline at end of file diff --git a/CMake/compilerflags/clang.cmake b/CMake/compilerflags/clang.cmake new file mode 100644 index 0000000000000000000000000000000000000000..98e13390792e78d65657c9660a1d75f238e62307 --- /dev/null +++ b/CMake/compilerflags/clang.cmake @@ -0,0 +1,68 @@ +############################################################################################################### +## +## clang +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -fPIC -Wbackslash-newline-escape") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + ############################################################################################################# + # disable warning + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wbackslash-newline-escape") #backslash and newline separated by space + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wcomment") #'/*' within block comment + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-Wbackslash-newline-escape") #backslash and newline separated by space + + ############################################################################################################# + # c++ 17 support + ############################################################################################################# + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++17") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++17") + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fext-numeric-literals") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wregister") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc33.cmake b/CMake/compilerflags/gcc33.cmake new file mode 100644 index 0000000000000000000000000000000000000000..2fc6eb1751b0dd49e26c5575809af13d154b60cc --- /dev/null +++ b/CMake/compilerflags/gcc33.cmake @@ -0,0 +1,44 @@ +############################################################################################################### +## +## gcc33 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -ffast-math -Wall -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-march=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-march=opteron" ) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-march=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-march=opteron" ) + ENDIF() + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + MESSAGE(STATUS "gcc33 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) + diff --git a/CMake/compilerflags/gcc34.cmake b/CMake/compilerflags/gcc34.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c0ac3476e4ef8f82e5381e7832ca172d9f8a4042 --- /dev/null +++ b/CMake/compilerflags/gcc34.cmake @@ -0,0 +1,44 @@ +############################################################################################################### +## +## gcc34 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -ffast-math -Wall -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + MESSAGE(STATUS "gcc34 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + diff --git a/CMake/compilerflags/gcc40.cmake b/CMake/compilerflags/gcc40.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c7bcf278e1cb992c900c828d94bab22d02eb9dd7 --- /dev/null +++ b/CMake/compilerflags/gcc40.cmake @@ -0,0 +1,54 @@ +############################################################################################################### +## +## gcc40 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + + ############################################################################################################### + ## 64Bit support + ############################################################################################################### + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + MESSAGE(STATUS "gcc40 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc41.cmake b/CMake/compilerflags/gcc41.cmake new file mode 100644 index 0000000000000000000000000000000000000000..60fc9de2a744879b2e2ea405092b91b0e1523db8 --- /dev/null +++ b/CMake/compilerflags/gcc41.cmake @@ -0,0 +1,51 @@ +############################################################################################################### +## +## gcc41 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + ############################################################################################################### + ## 64Bit support + ############################################################################################################### + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + MESSAGE(STATUS "gcc41 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc42.cmake b/CMake/compilerflags/gcc42.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cac77bf08dfbcff105faec0728efaab1be5d1add --- /dev/null +++ b/CMake/compilerflags/gcc42.cmake @@ -0,0 +1,57 @@ +############################################################################################################### +## +## gcc42 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + ############################################################################################################### + ## Flags + ############################################################################################################### + #Anmerkung: bei O3 oder "O2 mit finline-function" gibt es Probleme beim MuParser. bug im gcc? + #Bug kann durch "test" in MuParser/examples ueberprueft werden + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O2 -fomit-frame-pointer -funroll-all-loops -fPIC") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O2 -fomit-frame-pointer -finline-functions -funroll-all-loops") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + + ############################################################################################################### + ## 64Bit support + ############################################################################################################### + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc43.cmake b/CMake/compilerflags/gcc43.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1ff9c1a8b496b991866acac59b5589b865de8c13 --- /dev/null +++ b/CMake/compilerflags/gcc43.cmake @@ -0,0 +1,49 @@ +############################################################################################################### +## +## gcc43 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + + ############################################################################################################### + ## 64Bit support + ############################################################################################################### + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc44.cmake b/CMake/compilerflags/gcc44.cmake new file mode 100644 index 0000000000000000000000000000000000000000..9d3c2d57f2895f12a123f0f0c9ba21c2426c43a7 --- /dev/null +++ b/CMake/compilerflags/gcc44.cmake @@ -0,0 +1,54 @@ +############################################################################################################### +## +## gcc44 +## +############################################################################################################### + +#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) +#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + IF(CPU_TYPE MATCHES "Opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + ENDIF() + + + ############################################################################################################### + ## 64Bit support + ############################################################################################################### + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc45.cmake b/CMake/compilerflags/gcc45.cmake new file mode 100644 index 0000000000000000000000000000000000000000..fbd6824f829ad950417cdfd8370c558caed3d0aa --- /dev/null +++ b/CMake/compilerflags/gcc45.cmake @@ -0,0 +1,54 @@ +############################################################################################################### +## +## gcc45 +## +############################################################################################################### + +#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) +#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################### + ## Flags + ############################################################################################################### + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + # IF(CPU_TYPE MATCHES "Opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + # ENDIF() + + + # ############################################################################################################### + # ## 64Bit support + # ############################################################################################################### + # IF( ${use64BitOptions} ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + # ENDIF() + + + # ############################################################################################################### + # ## OpenMP support + # ############################################################################################################### + # IF(USE_OPENMP) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + # ENDIF() + + + # ############################################################################################################### + # ## mt support + # ############################################################################################################### + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + # IF(NOT APPLE) + # LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + # ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc46.cmake b/CMake/compilerflags/gcc46.cmake new file mode 100644 index 0000000000000000000000000000000000000000..fdf293b2b71910effddf0760e5d280e2192aa90a --- /dev/null +++ b/CMake/compilerflags/gcc46.cmake @@ -0,0 +1,54 @@ +############################################################################################################### +## +## gcc46 +## +############################################################################################################### + +#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) +#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type) + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################### + ## Flags + ############################################################################################################### + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + # IF(CPU_TYPE MATCHES "Opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" ) + # ENDIF() + + + # ############################################################################################################### + # ## 64Bit support + # ############################################################################################################### + # IF( ${use64BitOptions} ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + # ENDIF() + + + # ############################################################################################################### + # ## OpenMP support + # ############################################################################################################### + # IF(USE_OPENMP) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + # ENDIF() + + + # ############################################################################################################### + # ## mt support + # ############################################################################################################### + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + # IF(NOT APPLE) + # LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + # ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc47.cmake b/CMake/compilerflags/gcc47.cmake new file mode 100644 index 0000000000000000000000000000000000000000..2a6b91042c55e3bb0159030676310b541a952a2f --- /dev/null +++ b/CMake/compilerflags/gcc47.cmake @@ -0,0 +1,42 @@ +############################################################################################################### +## +## gcc47 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + MESSAGE(STATUS "gcc41 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc48.cmake b/CMake/compilerflags/gcc48.cmake new file mode 100644 index 0000000000000000000000000000000000000000..989afcc3e886ef1a92921982bdda4e720f7df436 --- /dev/null +++ b/CMake/compilerflags/gcc48.cmake @@ -0,0 +1,42 @@ +############################################################################################################### +## +## gcc48 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + MESSAGE(STATUS "gcc48 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc49.cmake b/CMake/compilerflags/gcc49.cmake new file mode 100644 index 0000000000000000000000000000000000000000..26f641ae19d9d0270f17e234ee37b3c5e0496f20 --- /dev/null +++ b/CMake/compilerflags/gcc49.cmake @@ -0,0 +1,42 @@ +############################################################################################################### +## +## gcc49 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + MESSAGE(STATUS "gcc49 has no OpenMP support -> OpenMP deactivated") + SET(USE_OPENMP "OFF") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc51.cmake b/CMake/compilerflags/gcc51.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1c4df2a693a8104ef4204715f4910d576a777336 --- /dev/null +++ b/CMake/compilerflags/gcc51.cmake @@ -0,0 +1,50 @@ +############################################################################################################### +## +## gcc51 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc52.cmake b/CMake/compilerflags/gcc52.cmake new file mode 100644 index 0000000000000000000000000000000000000000..41649c34a3b94c3703878554309c1c3cf032876e --- /dev/null +++ b/CMake/compilerflags/gcc52.cmake @@ -0,0 +1,50 @@ +############################################################################################################### +## +## gcc52 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc54.cmake b/CMake/compilerflags/gcc54.cmake new file mode 100644 index 0000000000000000000000000000000000000000..234797337a662621e76c23e621ecbe4e0c84c319 --- /dev/null +++ b/CMake/compilerflags/gcc54.cmake @@ -0,0 +1,50 @@ +############################################################################################################### +## +## gcc54 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc62.cmake b/CMake/compilerflags/gcc62.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5e80808ac777bf091434e1df1e43cff7a930c5f4 --- /dev/null +++ b/CMake/compilerflags/gcc62.cmake @@ -0,0 +1,50 @@ +############################################################################################################### +## +## gcc62 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc63.cmake b/CMake/compilerflags/gcc63.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c624265fa66e7c73bc9e7ad980f1ac5e9b6a670a --- /dev/null +++ b/CMake/compilerflags/gcc63.cmake @@ -0,0 +1,52 @@ +############################################################################################################### +## +## gcc63 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 17 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++17") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++17") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fext-numeric-literals") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0") + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gcc82.cmake b/CMake/compilerflags/gcc82.cmake new file mode 100644 index 0000000000000000000000000000000000000000..13857f5ceb6f882ae21d2235df15e60c0cbf5fbe --- /dev/null +++ b/CMake/compilerflags/gcc82.cmake @@ -0,0 +1,60 @@ +############################################################################################################### +## +## gcc82 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + ############################################################################################################# + # c++ 17 support + ############################################################################################################# + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++17") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++17") + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fext-numeric-literals") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wregister") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/gccGeneric.cmake b/CMake/compilerflags/gccGeneric.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c39f0f0d8e8ec55ec35a7f8e80fcdc31838089f9 --- /dev/null +++ b/CMake/compilerflags/gccGeneric.cmake @@ -0,0 +1,60 @@ +############################################################################################################### +## +## gcc generic +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + ############################################################################################################# + # Flags + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC") + + ############################################################################################################# + # 64Bit support + ############################################################################################################# + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-m64" ) + ENDIF() + + ############################################################################################################# + # OpenMP support + ############################################################################################################# + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp") + ENDIF() + + ############################################################################################################# + # mt support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + + ############################################################################################################# + # c++ 17 support + ############################################################################################################# + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++17") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++17") + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fext-numeric-literals") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wregister") + + + + IF(NOT APPLE) + LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc101.cmake b/CMake/compilerflags/icc101.cmake new file mode 100644 index 0000000000000000000000000000000000000000..236b940ee2e6bba93460256a8501a5451469111c --- /dev/null +++ b/CMake/compilerflags/icc101.cmake @@ -0,0 +1,51 @@ +############################################################################################################### +## +## intel10 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + ENDIF() + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops") + + IF(CPU_TYPE MATCHES "Opteron") + IF(WIN32) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-QxO") #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-QxO") #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs + ELSE() + #auf unserem cluster gibt es kein ss3 SET( CAB_CXX_FLAGS "${CAB_CXX_FLAGS} -xO") #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs + #gibt teils probleme beim ausfuehren: SET( CAB_C_FLAGS "${CAB_C_FLAGS} -xO") #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs + ENDIF() + ELSE() + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fast") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fast") + ENDIF() + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc130.cmake b/CMake/compilerflags/icc130.cmake new file mode 100644 index 0000000000000000000000000000000000000000..fa03ac7b095ddf86ab139f763b577e701eb633f0 --- /dev/null +++ b/CMake/compilerflags/icc130.cmake @@ -0,0 +1,38 @@ +############################################################################################################### +## +## intel10 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc140.cmake b/CMake/compilerflags/icc140.cmake new file mode 100644 index 0000000000000000000000000000000000000000..054326e248f3b1d2a0082d621bbc8d06d7a249d7 --- /dev/null +++ b/CMake/compilerflags/icc140.cmake @@ -0,0 +1,39 @@ +############################################################################################################### +## +## intel140 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc150.cmake b/CMake/compilerflags/icc150.cmake new file mode 100644 index 0000000000000000000000000000000000000000..62d6a440d39ddd41c2a620f3e32cff0ac50736a5 --- /dev/null +++ b/CMake/compilerflags/icc150.cmake @@ -0,0 +1,38 @@ +############################################################################################################### +## +## intel150 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc160.cmake b/CMake/compilerflags/icc160.cmake new file mode 100644 index 0000000000000000000000000000000000000000..963c503dea8ed282e905966df5d00d70559c2c3d --- /dev/null +++ b/CMake/compilerflags/icc160.cmake @@ -0,0 +1,43 @@ +############################################################################################################### +## +## intel160 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -ipo -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11" + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc170.cmake b/CMake/compilerflags/icc170.cmake new file mode 100644 index 0000000000000000000000000000000000000000..aa41f790419e37c463e50513715236ebfe3c6963 --- /dev/null +++ b/CMake/compilerflags/icc170.cmake @@ -0,0 +1,50 @@ +############################################################################################################### +## +## intel170 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -ipo -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1478") #auto_ptr warning from mu::Parser + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + + #Debug + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-g -traceback") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-qopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc180.cmake b/CMake/compilerflags/icc180.cmake new file mode 100644 index 0000000000000000000000000000000000000000..db9f3a70e299eae5eee2fbc71bdf248fbca35b64 --- /dev/null +++ b/CMake/compilerflags/icc180.cmake @@ -0,0 +1,51 @@ +############################################################################################################### +## +## intel180 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -ipo -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1478") #auto_ptr warning from mu::Parser + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always -xCORE-AVX512 -qopt-zmm-usage=high") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always -xCORE-AVX512 -qopt-zmm-usage=high") + + #Debug + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-g -traceback") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-qopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc190.cmake b/CMake/compilerflags/icc190.cmake new file mode 100644 index 0000000000000000000000000000000000000000..ff7aafd6da9a9c1e5e922acf21ad59dbb65457ba --- /dev/null +++ b/CMake/compilerflags/icc190.cmake @@ -0,0 +1,51 @@ +############################################################################################################### +## +## intel190 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + #~ IF( ${use64BitOptions} ) + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + #~ ENDIF() + + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor +#~ + #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -ipo -fno-alias -mcmodel=medium -qopt-streaming-stores=always") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1478") #auto_ptr warning from mu::Parser + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always -xCORE-AVX512 -qopt-zmm-usage=high") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-xHOST -O3 -ip -fno-alias -mcmodel=medium -qopt-streaming-stores=always -xCORE-AVX512 -qopt-zmm-usage=high") + + #Debug + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-g -traceback") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-qopenmp") + ENDIF() + + + ############################################################################################################### + ## mt support + ############################################################################################################### + #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + #LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + + ############################################################################################################# + # c++ 11 support + ############################################################################################################# + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/icc91.cmake b/CMake/compilerflags/icc91.cmake new file mode 100644 index 0000000000000000000000000000000000000000..351aa8fdf17b3a836e656e4921944856f73737a1 --- /dev/null +++ b/CMake/compilerflags/icc91.cmake @@ -0,0 +1,47 @@ +############################################################################################################### +## +## intel9 +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + IF( ${use64BitOptions} ) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) + ENDIF() + + #IF( ${compiler} MATCHES "INTEL_91_IPO") + # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-ipo" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-ipo" ) + # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-opt-mem-bandwidth2" ) + #ENDIF( ${compiler} MATCHES "INTEL_91_IPO") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fast -fomit-frame-pointer -finline-functions") + + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd68" ) #integer conversion resulted in a change of sign + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd186") # pointless comparison of unsigned integer with zero + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327") #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor + + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266") #function "__GKfree" declared implicitly + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fast -fomit-frame-pointer -finline-functions") + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp") + ENDIF() + + ############################################################################################################### + ## mt support + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread") + LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread") + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) diff --git a/CMake/compilerflags/msvc19_32.cmake b/CMake/compilerflags/msvc19_32.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d10f156430ded744a38fd99ceb38e1dc6869b1f8 --- /dev/null +++ b/CMake/compilerflags/msvc19_32.cmake @@ -0,0 +1,39 @@ +############################################################################################################### +## +## MSVC 2019 (Version 16.0) 32bit (msvc16_64) +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + IF(NOT ${use64BitOptions}) + MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc16_64") + ENDIF() + + ############################################################################################################### + ## USE_UNSECURE_STL_VECTORS_RELEASE ? + ############################################################################################################### + OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF) + IF(USE_UNSECURE_STL_VECTORS_RELEASE) + # More MSVC specific compilation flags + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS") + ENDIF() + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy... + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #boost support + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + diff --git a/CMake/compilerflags/msvc19_64.cmake b/CMake/compilerflags/msvc19_64.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5e95f57c6914e345d0b775c9bbc25b7807b62e08 --- /dev/null +++ b/CMake/compilerflags/msvc19_64.cmake @@ -0,0 +1,39 @@ +############################################################################################################### +## +## MSVC 2019 (Version 16.0) 64bit (msvc16_64) +## +############################################################################################################### + +MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + + IF(NOT ${use64BitOptions}) + MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc16_64") + ENDIF() + + ############################################################################################################### + ## USE_UNSECURE_STL_VECTORS_RELEASE ? + ############################################################################################################### + OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF) + IF(USE_UNSECURE_STL_VECTORS_RELEASE) + # More MSVC specific compilation flags + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS") + ENDIF() + + ############################################################################################################### + ## Flags + ############################################################################################################### + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE") + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy... + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #boost support + + ############################################################################################################### + ## OpenMP support + ############################################################################################################### + IF(USE_OPENMP) + LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp") + ENDIF() + +ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions) + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..761289edff637b8b07f16a0288cec85024aeabd8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +PROJECT(VirtualFluids) + +set(SOURCE_ROOT "../source") + +SET(USE_INTEL OFF CACHE BOOL "include Intel compiler support") +SET(USE_GCC OFF CACHE BOOL "include gcc compiler support") + +#CAB +INCLUDE("CMake/CMakeCABMacros.txt") + +LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DNOMINMAX) + +IF(${USE_INTEL}) + SET(CAB_ADDITIONAL_LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS} -parallel) +ENDIF() + +IF(${USE_GCC}) + SET(CAB_ADDITIONAL_LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS} -lgomp) +ENDIF() + +add_subdirectory(VirtualFluidsCore) + +set(APPS_ROOT "${SOURCE_ROOT}/Applications") +INCLUDE(${APPS_ROOT}/Applications.cmake) + diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000000000000000000000000000000000000..b4e13b152135c1fbc01cbb9741f1b1e66d83c2f4 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,676 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + + diff --git a/Documentation/doxygen/VF_Doxyfile.dox b/Documentation/doxygen/VF_Doxyfile.dox new file mode 100644 index 0000000000000000000000000000000000000000..36f2954a21c22d26d373fb39940340990dfe553b --- /dev/null +++ b/Documentation/doxygen/VF_Doxyfile.dox @@ -0,0 +1,2561 @@ +# Doxyfile 1.8.16 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = VirtualFluidsCPU + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = VirtualFluidsLogo_lowResolution.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../../ \ + ../../VirtualFluidsCore \ + ../../ThirdParty + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = main.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = YES + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: https://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: https://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES, to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO, the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES, the include files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = VF_FETOL \ + VF_MPI \ + VF_METIS \ + VF_ZOLTAN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# If set to YES the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. + +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/Documentation/doxygen/VirtualFluidsLogo_lowResolution.png b/Documentation/doxygen/VirtualFluidsLogo_lowResolution.png new file mode 100644 index 0000000000000000000000000000000000000000..06325f4d26a31a0b0a3b003ed57708f932eb5865 Binary files /dev/null and b/Documentation/doxygen/VirtualFluidsLogo_lowResolution.png differ diff --git a/ThirdParty/MuParser/CMakePackage.txt b/ThirdParty/MuParser/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b3edddf003d9a8052c848fe2b6c78f4cc2ce28a --- /dev/null +++ b/ThirdParty/MuParser/CMakePackage.txt @@ -0,0 +1,36 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption outSourceGroupName) + +IF( ${outOption} ) + + #verzeichnis als std-include adden + INCLUDE_DIRECTORIES( ${CURRENT_DIR}/include ) + + OPTION(USE_MUPARSER_AS_LIB "MuParser will be compiled as lib" ON) + + IF(USE_MUPARSER_AS_LIB) + FILE( GLOB muparser_HEADER_FILES ${CURRENT_DIR}/include/*.h ) + FILE( GLOB muparser_CXX_FILES ${CURRENT_DIR}/src/*.cpp ) + + SET(MUPARSER_SRC_FILES ${muparser_HEADER_FILES} ${muparser_CXX_FILES}) + + ADD_LIBRARY(muParserLib ${MUPARSER_SRC_FILES}) + + #lib projekt hinzufuegen + LIST(APPEND CAB_ADDITIONAL_LINK_LIBRARIES muParserLib) + + ADD_TARGET_PROPERTIES(muParserLib COMPILE_FLAGS "-I${CURRENT_DIR}/include") + + #compilerflags aktuellem projekt hinzufuegen + ADD_COMPILER_FLAGS_TO_PROJECT(${CAB_COMPILER} "muParserLib" "CXX" "STATIC") + + ELSE() #not as lib + SET( CURRENT_DIR_TMP ${CURRENT_DIR} ) #wird im nächsten befehl geaendert + INCLUDE( ${CURRENT_DIR_TMP}/include/CMakePackage.txt) + INCLUDE( ${CURRENT_DIR_TMP}/src/CMakePackage.txt) + ENDIF() + +ENDIF( ${outOption} ) + + + diff --git a/ThirdParty/MuParser/Changes.txt b/ThirdParty/MuParser/Changes.txt new file mode 100644 index 0000000000000000000000000000000000000000..87077a5d972cf2f027bb2211aff587cf4469c7e4 --- /dev/null +++ b/ThirdParty/MuParser/Changes.txt @@ -0,0 +1,557 @@ +####################################################################### +# # +# # +# __________ # +# _____ __ __\______ \_____ _______ ______ ____ _______ # +# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ # +# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ # +# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| # +# \/ \/ \/ \/ # +# Fast math parser Library # +# # +# Copyright (C) 2015 Ingo Berg # +# # +# Web: muparser.beltoforion.de # +# e-mail: muparser@beltoforion.de # +# # +# # +####################################################################### + + +History: +-------- + +Rev 2.2.5: 27.04.2015 +--------------------- + Changes: + * example2 extended to work with UNICODE character set + * Applied patch from Issue 9 + + Bugfixes: + * muChar_t in muParserDLL.h was not set properly when UNICODE was used + * muparser.dll did not build on UNICODE systems + +Rev 2.2.4: 02.10.2014 +--------------------- + Changes: + * explicit positive sign allowed + + Bugfixes: + * Fix for Issue 6 (https://code.google.com/p/muparser/issues/detail?id=6) + * String constants did not work properly. Using more than a single one + was impossible. + * Project Files for VS2008 and VS2010 removed from the repository + * Fix for Issue 4 (https://code.google.com/p/muparser/issues/detail?id=4) + * Fix for VS2013 64 bit build option + * return type of ParserError::GetPos changed to int + * OpenMP support enabled in the VS2013 project files and precompiled windows DLL's + * Bulkmode did not evaluate properly if "=" and "," operator was used in the expression + +Rev 2.2.3: 22.12.2012 +--------------------- + + Removed features: + * build files for msvc2005, borland and watcom compiler were removed + + Bugfixes: + * Bugfix for Intel Compilers added: The power operator did not work properly + with Intel C++ composer XE 2011. + (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1) + * Issue 3509860: Callbacks of functions with string parameters called twice + (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979) + * Issue 3570423: example1 shows slot number in hexadecimal + (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979) + * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition: + - division by zero in constant expressions was reported with the code "ec_GENERIC" + instead of "ecDIV_BY_ZERO" + - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions + + +Rev 2.2.2: 18.02.2012 +--------------------- + Bugfixes: + * Optimizer did'nt work properly for division: + (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825) + +Rev 2.2.1: 22.01.2012 +--------------------- + Bugfixes: + * Optimizer bug in 64 bit systems fixed + (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1) + +Rev 2.2.0: 22.01.2012 +--------------------- + Improvements: + * Optimizer rewritten and improved. In general: more optimizations are + now applied to the bytecode. The downside is that callback Functions + can no longer be flagged as non-optimizable. (The flag is still present + but ignored) This is necessary since the optimizer had to call the + functions in order to precalculate the result (see Bugfixes). These calls + posed a problems for callback functions with side effects and if-then-else + clauses in general since they undermined the shortcut evaluation prinziple. + + Bugfixes: + * Infix operators where not properly detected in the presence of a constant + name starting with an underscore which is a valid character for infix + operators too (i.e. "-_pi"). + * Issue 3463353: Callback functions are called twice during the first call to eval. + * Issue 3447007: GetUsedVar unnecessaryly executes callback functions. + + +Rev 2.1.0: 19.11.2011 +--------------------- + New feature: + * Function atan2 added + + Bugfixes: + * Issue 3438380: Changed behaviour of tellg with GCC >4.6 led to failures + in value detection callbacks. + * Issue 3438715: only "double" is a valid MUP_BASETYPE + MUP_BASETYPE can now be any of: + float, + double, + long double, + short, + unsigned short, + unsigned int, + long, + unsigned long. + Previousely only floating point types were allowed. + Using "int" is still not allowed! + * Compiler issues with GCC 4.6 fixed + * Custom value recognition callbacks added with AddValIdent had lower + priority than built in functions. This was causing problems with + hex value recognition since detection of non hex values had priority + over the detection of hex values. The "0" in the hex prefix "0x" would + be read as a separate non-hex number leaving the rest of the expression + unparseable. + +Rev 2.0.0: 04.09.2011 +--------------------- +This release introduces a new version numbering scheme in order to make +future changes in the ABI apparent to users of the library. The number is +now based on the SONAME property as used by GNU/Linux. + + Changes: + * Beginning with this version all version numbers will be SONAME compliant + * Project files for MSVC2010 added + * Project files for MSVC2003 removed + * Bytecode parsing engine cleaned up and rewritten + * Retrieving all results of expressions made up of comma separate + subexpressions is now possible with a new Eval overload. + * Callback functions with fixed number of arguments can now have up to 10 + Parameters (previous limit was 5) + + New features: + * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." ) + * new intrinsic binary operators: "&&", "||" (logical and, or) + * A new bulkmode allows submitting large arrays as variables to compute large + numbers of expressions with a single call. This can drastically improve + parsing performance when interfacing the library from managed languages like + C#. (It doesn't bring any performance benefit for C++ users though...) + + Removed features: + * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let + users the freedom of defining them on their own versions (either as logical or bitwise + operators). + * Implementation for complex numbers removed. This was merely a hack. If you + need complex numbers try muParserX which provides native support for them. + (see: http://beltoforion.de/muparserx/math_expression_parser_en.html) + + Bugfixes: + * User defined operators could collide with built in operators that entirely + contained their identifier. i.e. user defined "&" would not work with the built + in "&&" operator since the user defined operator was detected with a higher + priority resulting in a syntax error. + * Detection of unknown variables did not work properly in case a postfix operator + was defined which was part of the undefined variable. + i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did + not detect "multi" as an undefined variable. + (Reference: http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979) + * Postfix operators sharing the first few characters were causing bogus parsing exception. + (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979) + +Rev 1.34: 04.09.2010 +-------------------- + Changes: + * The prefix needed for parsing hex values is now "0x" and no longer "$". + * AddValIdent reintroduced into the DLL interface + + New features: + * The associativity of binary operators can now be changed. The pow operator + is now right associative. (This is what Mathematica is using) + * Seperator can now be used outside of functions. This allows compound + expressions like: + "a=10,b=20,c=a*b" The last "argument" will be taken as the return value + + Bugfixes: + * The copy constructor did not copy binary operator definitions. Those were lost + in the copied parser instance. + * Mixing special characters and alphabetic characters in binary operator names + led to inconsistent parsing behaviour when parsing expressions like "a ++ b" + and "a++b" when "++" is defined as a binary operator. Binary operators must + now consist entirely of special characters or of alphabetic ones. + (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1) + * User defined operators were not exactly handled like built in operators. This + led to inconsistencies in expression evaluation when using them. The results + differed due to slightly different precedence rules. + * Using empty string arguments ("") would cause a crash of muParser + + +Rev 1.32: 29.01.2010 +-------------------- + + Changes: + * "example3" renamed to "example2" + * Project/Makefiles files are now provided for: + - msvc2003 + - msvc2005 + - msvc2008 + - watcom (makefile) + - mingw (makefile) + - bcc (makefile) + * Project files for borland cpp builder were removed + + + New features: + * Added function returning muparsers version number + * Added function for resetting the locale + + + Bugfixes: + * Changes example1 in order to fix issues with irritating memory leak reports. + Added conditional code for memory leak detection with MSVC in example1. + (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx) + * Fixed some warnings for gcc + + + +Rev 1.31cp: 15.01.2010 (Maintainance release for CodeProject) +---------------------- + + Changes: + * Archive structure changed + * C# wrapper added + * Fixed issued that prevented compiling with VS2010 Beta2 + + +Rev 1.30: 09.06.2008 +-------------------- + + Changes: + * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy. + + New features: + * Setting thousands separator and decimal separator is now possible + + Bugfixes: + * The dll interface did not provide a callback for functions without any arguments. + + +Rev 1.29: Januar 2008 +--------------------- + + Unrelease Version available only via SVN. + + +Rev 1.28: 02. July, 2007 +--------------------------- + + Library changes: + * Interface for the dynamic library changed and extended to create an interface + using pure C functions only. + * mupInit() removed + + Build system: + * MSVC7 Project files removed in favor of MSVC8 + + Bugfixes: + * The dynamic library did not build on other systems than linux due to a misplaced + preprocessor definition. This is fixed now. + + +Rev 1.27: +--------------------------- + + Build system: + * Modified build\ directory layout introducing some subfolders + for the various IDE supported + * Project files for BCB and MSVC7 added + * Switched to use bakefile 0.2.1 which now correctly creates the + "make uninstall" target for autoconf's Makefile.in + * Now the library debug builds are named "muparserd" instead of "muparser" + to allow multiple mixed release/debug builds to coexist; so e.g. on Windows + when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib" + + New Features: + * Factory functions can now take a user defined pointer + * String functions can now be used with up to two additional + double parameters + * Support for UNICODE character types added + * Infix operator priority can now be changed by the user + + Bugfixes: + * An internal error was raised when evaluating an empty + expressions + * The error message raised in case of name collisions between + implicitely defined variables and postfix operators did contain + misleading data. + + +Rev 1.26: (unofficial release) +------------------------------ + + New Features: + * Unary operator precedence can now be changed by the user. + + +Rev 1.25: 5. February, 2006 +--------------------------- + + Build system: (special thanks to Francesco Montorsi for implementing it!) + * created a bakefile-based build system which adds support for the following win32 compilers: + -> MS visual C++ (6 and .NET) + -> BorlandC++ (5 or greater) + -> Mingw32 (tested with gcc 3.2) + -> Watcom (not tested) + and for GCC on Unix (using a standard autoconf's configure script). + + Compatibility improvements: + * fixed some small warnings when using -Wall with GCC on Unix + * added inclusion guards for win32-specific portions of code + * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler. + + +Rev 1.24: 29. October, 2005 +--------------------------- + +Changes: + + Compatibility improvements: + * parser now works on 64 bit compilers + * (bytecode base datatype can now be changed freely) + + +Rev 1.23: 19. October, 2005 +--------------------------- + +Changes: + + Bugfixes: + * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug. + + New features: + * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6 + + +Rev 1.22: October, 2005 +----------------------- + +Release notes: + +All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with +gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. +This should make the code cleaner. The Borland Project files were removed. If you want to use it +with Borland either use the dll version or create your own project files. I can't support it since I don't +have this compiler at hand. + +Changes: + + Project Changes: + * Borland project files removed + (The code should still compile with BCB but I cant provide you with project files) + + Internal Changes: + * unnecessary template files have been removed: + - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp + - removed Files: muIParserTypes.h + + +Rev 1.2 / 1.21: April, 2005 +--------------------------- + +Release Notes: +First of all the interface has changed so this version is not backwards compatible. +After receiving a couple of questions about it, this version features support for +user defined binary operators. Consequently the built in operators can now be +turned off, thus you can deactivate them and write complete customized parser +subclasses that only contain the functionality you want. Another new feature is +the introduction of callback functions taking string arguments, implicit +generation of variables and the Assignement operator. + + Functionality + * New built in operator: xor; Logical xor. + * New built in operator: Assignement operator; Defining variables in terms of + other variables/constants + * New feature: Strings as arguments for callback functions + * New feature: User defined binary operators + * New feature: ParserInt a class with a sample implementation for + integer numbers. + * New feature: Callbacks to value regognition functions. + + * Removed: all predefined postfix operators have been removed. + * New project file: Now comes with a ready to use windows DLL. + * New project file: Makefile for cygwin now included. + * New example: Example3 shows usage of the DLL. + + Interface changes + * New member function: DefineOprt For adding user defined binary operators. + * New member function: EnableBuiltInOprt(bool) Enables/Disables built in + binary operators. + * New member function: AddValIdent(...) to add callbacks for custom value + recognition functions. + * Removed: SetVar(), SetConst(). + * Renamed: Most interface functions have been renamed + * Changed: The type for multiargument callbacks multfun_type has changed. + It no longer takes a std::vector as input. + + Internal changes + * new class muParserTokenReader.h encapsulates the token identification + and token assignement. + * Internal handling of function callbacks unified as a result the performance + of the bytecode evaluation increased. + + +Rev 1.10 : December 30, 2004 +---------------------------- + +Release Notes: +This version does not contain major new feature compared to V1.07 but its internal structure has +changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode +parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you +can change its value datatype. It should work on 64-bit systems. For this reason I supply both +versions for download. If you use V1.07 and are happy with it there is no need for updating +your version. + + * New example program: Archive now contains two demo programs: One for standard C++ and one for + managed C++. + * New member function: RemoveVar(...) can be used for removing a single variable from the internal + storage. + * New member function: GetVar() can be used for querying the variable names and pointers of all + variables defined in the parser. + * New member function: GetConst() can be used for querying all defined constants and their values. + * New member function: GetFunDef() can be used for querying all defined functions and the number of + arguments they expect. + * Internal structure changed; hanging base datatype at compile time is now possible. + * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now. + * Bugfix: Variable names must will now be tested if they conflict with constant or function names. + * Internal change: Removed most dependencies from the C-string libraries. + * Internal change: Bytecode is now stored in a separate class: ParserByteCode.h + * Internal change: GetUsedVar() does no longer require that variables are defined at time of call. + * Internal change: Error treatment changed. ParserException is no longer derived from + std::runtime_error; Internal treatment of Error messages changed. + * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars() + they are used for defining the charset allowed for variable-, operator- and + function names. + + +Rev 1.09 : November 20, 2004 +---------------------------- + + * New member function: RemoveVar(...) can be used for removing a single variable from the internal + storage. + * Internal structure changed; changing base datatype at compile time is now possible. + * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now. + * Internal change: Removed most dependencies from the C-string libraries. + * Internal change: Bytecode is now stored in a seperate class: ParserByteCode.h. + * Internal change: GetUsedVar() does no longer require that variables are defined at time of call. + * Internal change: Error treatment changed. ParserException is no longer derived from + std::runtime_error; Internal treatment of Error messages changed. + * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars() + they are used for defining the charset allowed for variable-, operator- and function names. + + +Rev 1.08 : November, 2004 +------------------------- + + * unpublished; experimental template version with respect to data type and underlying string + type (string <-> widestring). The idea was dropped... + + +Rev 1.07 : September 4 2004 +--------------------------- + + * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some + issues left. + * Improved portability; Changes in order to allow compiling on BCB. + * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with + respect to a certain variable; added in muParser.h. + + +Rev 1.06 : August 20 2004 +------------------------- + + * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter + indicating that the function can not be optimized. + * Internal changes: muParserStack.h simplified; refactorings + * Parser is now distributed under the MIT License; all comments changed accordingly. + + +Rev 1.05 : August 20 2004 +------------------------- + + * Variable/constant names will now be checked for invalid characters. + * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar(). + * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat). + * Predefined functions with variable number of arguments added: sum, avg, min, max. + * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp(). + * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp(). + * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly. + * Internal changes: static array removed in Command code calculation routine; misc. changes. + + +Rev 1.04 : August 16 2004 +------------------------- + + * Support for functions with variable number of arguments added. + * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h; + changed: Parser.h, Parser.cpp. + * Bug in the bytecode calculation function fixed (affected the unary minus operator). + * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat). + + +Rev 1.03 : August 10 2004 +------------------------- + + * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(), + ClearPostOp(). + * Minor changes to the bytecode parsing routine. + * User defined functions can now have up to four parameters. + * Performance optimized: simple formula optimization added; (precalculation of constant parts of the + expression). + * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly. + + +Rev 1.02 : July 30 2004 +----------------------- + + * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(), + ClearConst(). + * Single variables can now be added using AddVar(); you have now the choice of adding them either + one by one or all at the same time using SetVar(const varmap_type &a_vVar). + * Internal handling of variables changed, is now similar to function handling. + * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to + derive new parsers with a modified set of default functions and constants. + * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold + function parameter count. + + +Rev 1.01 : July 23 2004 +----------------------- + + * Support for user defined functions has been added; new functions: AddFun(), ClearFun(), + InitFunctions(). + * Built in constants have been removed; the parser contained undocumented built in + constants pi, e. + There was the possibility of name conflicts with user defined variables. + * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only + argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3 + arguments (array of names, array of pointers, and array length) is now marked as deprecated. + * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for + base 10, and ln for base e. + + +Rev 1.00 : July 21 2004 +----------------------- + + * Initial release diff --git a/ThirdParty/MuParser/Install.txt b/ThirdParty/MuParser/Install.txt new file mode 100644 index 0000000000000000000000000000000000000000..ed8ae9728225a79668c96db46d42ffda77f610a6 --- /dev/null +++ b/ThirdParty/MuParser/Install.txt @@ -0,0 +1,133 @@ +####################################################################### +# # +# # +# __________ # +# _____ __ __\______ \_____ _______ ______ ____ _______ # +# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ # +# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ # +# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| # +# \/ \/ \/ \/ # +# Fast math parser Library # +# # +# Copyright (C) 2012 Ingo Berg # +# # +# Web: muparser.beltoforion.de # +# e-mail: muparser@beltoforion.de # +# # +# # +####################################################################### + + + + Contents + ======== + + 1. Installation on win32 + 2. Installation on unix + 2.1 Other miscellaneous info Unix-specific + 3. Where to ask for help + + + + 1. Installation on win32 + ======================== + + muParser supports various win32 command-line compilers: + -> mingw + -> watcom + -> microsoft CL + and provides also the project files for MSVC6 IDE. + + In order to compile muParser from makefiles, open an MSDOS + prompt and then move to the muParser/build directory and + type: + + mingw32-make -fmakefile.mingw for mingw + nmake -fmakefile.vc for msvc + make -fmakefile.bcc for borland + wmake -fmakefile.wat for watcom + + All makefiles supports the following options: + + # Set to 1 to build debug version [0,1] + # 0 - Release + # 1 - Debug + DEBUG = 0 + + # Set to 1 to build shared (DLL) version [0,1] + # 0 - Static + # 1 - DLL + SHARED = 0 + + # Set to 1 to compile samples [0,1] + SAMPLES = 1 + + The muParser library is created in the 'lib' folder and the sample + binaries are created in samples\example1 or samples\example2. + + NOTE: samples\example1 can be compiled *only* when building + muParser as a STATIC library (SHARED=0). + samples\example2 can be compiled *only* when building + muParser as a SHARED library (SHARED=1). + + + + 2. Installation on Unix/Linux + ============================= + + muParser can be installed just extracting the sources somewhere + and then, from a terminal, typing: + + cd [path to muParser] + ./configure [--enable-shared=yes/no] [--enable-samples=yes/no] + [--enable-debug=yes/no] + make + [sudo*] make install + [sudo*] ldconfig + cd samples/example1 + ./example1 + + * = this command must be executed with root permissions and thus + you have to use 'sudo' or just 'su' to gain root access. + Note that installation and ldconfig are not strictly required unless + you built in shared mode. + + The "make" step will create the muParser library in 'lib' and the + sample binary in samples/example1. + The samples/example2 is win32-specific and thus won't be built. + + + + 2.1 Other miscellaneous info Unix-specific + ========================================== + + If you don't like to have your muParser folder filled by temporary + files created by GCC, then you can do the following: + + mkdir mybuild && cd mybuild && ../configure && make + + to put all object files in the "mybuild" directory. + + If you want to use muParser library in your programs, you can use + the pkg-config program (this works only if muParser was installed + with 'make install' !). The commands: + + pkg-config muparser --cflags + pkg-config muparser --libs + + will return all useful info you need to build your programs against + muParser ! + + + + 3. Where to ask for help + ======================== + + If you find problems with either compilation, installation or usage + of muParser, then you can ask in the muParser forum at: + + https://sourceforge.net/forum/forum.php?forum_id=462843 + + For more info about muParser, visit: + http://sourceforge.net/projects/muparser/ + http://muparser.sourceforge.net diff --git a/ThirdParty/MuParser/License.txt b/ThirdParty/MuParser/License.txt new file mode 100644 index 0000000000000000000000000000000000000000..64286563696c3eb4d0c55ff572ac5c9aae3aecaa --- /dev/null +++ b/ThirdParty/MuParser/License.txt @@ -0,0 +1,35 @@ +####################################################################### +# # +# # +# __________ # +# _____ __ __\______ \_____ _______ ______ ____ _______ # +# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ # +# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ # +# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| # +# \/ \/ \/ \/ # +# Fast math parser Library # +# # +# Copyright (C) 2011 Ingo Berg # +# # +# Web: muparser.beltoforion.de # +# e-mail: muparser@beltoforion.de # +# # +# # +####################################################################### + + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ThirdParty/MuParser/docs/Doxyfile b/ThirdParty/MuParser/docs/Doxyfile new file mode 100644 index 0000000000000000000000000000000000000000..9793afe34369e1dc4c9300d19984a89952d06ee1 --- /dev/null +++ b/ThirdParty/MuParser/docs/Doxyfile @@ -0,0 +1,1563 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "muParser API -" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.35 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = html/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 16 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set +# FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = html/misc/Main.txt \ + html/misc/example.txt \ + ../src/ \ + ../include/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = html/misc/ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = NO + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = classdocu/ + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = html/misc/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = jpg + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = "C:\Program Files (x86)\Graphviz2.20\bin" + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/ThirdParty/MuParser/docs/muparser_doc.html b/ThirdParty/MuParser/docs/muparser_doc.html new file mode 100644 index 0000000000000000000000000000000000000000..09dbba14393dc6c06a6a64d126f8ad29439e4146 --- /dev/null +++ b/ThirdParty/MuParser/docs/muparser_doc.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html style="height:100%;"> +<head> +</head> + +<body style="height:100%; overflow:hidden;"> + + <div style="border: 0px; position:absolute; top:0px; left:0px; width:100%; bottom:0px; padding:0px; margin:0px;"> + <iframe src="http://muparser.beltoforion.de" style="border: 0px; width:100%; height:100%;"> + Sorry, your browser doesn't support IFrames. Click <a href="http://muparser.beltoforion.de">here</a> to load the muparser documentation directly. + </iframe> + </div> +</body> + +</html> diff --git a/ThirdParty/MuParser/include/muParser.h b/ThirdParty/MuParser/include/muParser.h new file mode 100644 index 0000000000000000000000000000000000000000..451cf703611b7932f421254b6dfcb2940d18978a --- /dev/null +++ b/ThirdParty/MuParser/include/muParser.h @@ -0,0 +1,115 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef MU_PARSER_H +#define MU_PARSER_H + +//--- Standard includes ------------------------------------------------------------------------ +#include <vector> + +//--- Parser includes -------------------------------------------------------------------------- +#include "muParserBase.h" +#include "muParserTemplateMagic.h" + +/** \file + \brief Definition of the standard floating point parser. +*/ + +namespace mu +{ + /** \brief Mathematical expressions parser. + + Standard implementation of the mathematical expressions parser. + Can be used as a reference implementation for subclassing the parser. + + <small> + (C) 2011 Ingo Berg<br> + muparser(at)beltoforion.de + </small> + */ + /* final */ class Parser : public ParserBase + { + public: + + Parser(); + + virtual void InitCharSets(); + virtual void InitFun(); + virtual void InitConst(); + virtual void InitOprt(); + virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); + + value_type Diff(value_type *a_Var, + value_type a_fPos, + value_type a_fEpsilon = 0) const; + + protected: + + // Trigonometric functions + static value_type Sin(value_type); + static value_type Cos(value_type); + static value_type Tan(value_type); + static value_type Tan2(value_type, value_type); + // arcus functions + static value_type ASin(value_type); + static value_type ACos(value_type); + static value_type ATan(value_type); + static value_type ATan2(value_type, value_type); + + // hyperbolic functions + static value_type Sinh(value_type); + static value_type Cosh(value_type); + static value_type Tanh(value_type); + // arcus hyperbolic functions + static value_type ASinh(value_type); + static value_type ACosh(value_type); + static value_type ATanh(value_type); + // Logarithm functions + static value_type Log2(value_type); // Logarithm Base 2 + static value_type Log10(value_type); // Logarithm Base 10 + static value_type Ln(value_type); // Logarithm Base e (natural logarithm) + // misc + static value_type Exp(value_type); + static value_type Abs(value_type); + static value_type Sqrt(value_type); + static value_type Rint(value_type); + static value_type Sign(value_type); + + // Prefix operators + // !!! Unary Minus is a MUST if you want to use negative signs !!! + static value_type UnaryMinus(value_type); + static value_type UnaryPlus(value_type); + + // Functions with variable number of arguments + static value_type Sum(const value_type*, int); // sum + static value_type Avg(const value_type*, int); // mean value + static value_type Min(const value_type*, int); // minimum + static value_type Max(const value_type*, int); // maximum + + static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal); + }; +} // namespace mu + +#endif + diff --git a/ThirdParty/MuParser/include/muParserBase.h b/ThirdParty/MuParser/include/muParserBase.h new file mode 100644 index 0000000000000000000000000000000000000000..a37927306ebe44c8b55de6f56cfd47edbb6b9349 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserBase.h @@ -0,0 +1,317 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef MU_PARSER_BASE_H +#define MU_PARSER_BASE_H + +//--- Standard includes ------------------------------------------------------------------------ +#include <cmath> +#include <string> +#include <iostream> +#include <map> +#include <memory> +#include <locale> +#include <limits.h> + +//--- Parser includes -------------------------------------------------------------------------- +#include "muParserDef.h" +#include "muParserStack.h" +#include "muParserTokenReader.h" +#include "muParserBytecode.h" +#include "muParserError.h" + + +namespace mu +{ +/** \file + \brief This file contains the class definition of the muparser engine. +*/ + +//-------------------------------------------------------------------------------------------------- +/** \brief Mathematical expressions parser (base parser engine). + \author (C) 2013 Ingo Berg + + This is the implementation of a bytecode based mathematical expressions parser. + The formula will be parsed from string and converted into a bytecode. + Future calculations will be done with the bytecode instead the formula string + resulting in a significant performance increase. + Complementary to a set of internally implemented functions the parser is able to handle + user defined functions and variables. +*/ +class ParserBase +{ +friend class ParserTokenReader; + +private: + + /** \brief Typedef for the parse functions. + + The parse function do the actual work. The parser exchanges + the function pointer to the parser function depending on + which state it is in. (i.e. bytecode parser vs. string parser) + */ + typedef value_type (ParserBase::*ParseFunction)() const; + + /** \brief Type used for storing an array of values. */ + typedef std::vector<value_type> valbuf_type; + + /** \brief Type for a vector of strings. */ + typedef std::vector<string_type> stringbuf_type; + + /** \brief Typedef for the token reader. */ + typedef ParserTokenReader token_reader_type; + + /** \brief Type used for parser tokens. */ + typedef ParserToken<value_type, string_type> token_type; + + /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ + static const int s_MaxNumOpenMPThreads = 16; + + public: + + /** \brief Type of the error class. + + Included for backwards compatibility. + */ + typedef ParserError exception_type; + + static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); + + ParserBase(); + ParserBase(const ParserBase &a_Parser); + ParserBase& operator=(const ParserBase &a_Parser); + + virtual ~ParserBase(); + + value_type Eval() const; + value_type* Eval(int &nStackSize) const; + void Eval(value_type *results, int nBulkSize); + + int GetNumResults() const; + + void SetExpr(const string_type &a_sExpr); + void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL); + + void SetDecSep(char_type cDecSep); + void SetThousandsSep(char_type cThousandsSep = 0); + void ResetLocale(); + + void EnableOptimizer(bool a_bIsOn=true); + void EnableBuiltInOprt(bool a_bIsOn=true); + + bool HasBuiltInOprt() const; + void AddValIdent(identfun_type a_pCallback); + + /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) + \brief Define a parser function without arguments. + \param a_strName Name of the function + \param a_pFun Pointer to the callback function + \param a_bAllowOpt A flag indicating this function may be optimized + */ + template<typename T> + void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) + { + AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() ); + } + + void DefineOprt(const string_type &a_strName, + fun_type2 a_pFun, + unsigned a_iPri=0, + EOprtAssociativity a_eAssociativity = oaLEFT, + bool a_bAllowOpt = false); + void DefineConst(const string_type &a_sName, value_type a_fVal); + void DefineStrConst(const string_type &a_sName, const string_type &a_strVal); + void DefineVar(const string_type &a_sName, value_type *a_fVar); + void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true); + void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true); + + // Clear user defined variables, constants or functions + void ClearVar(); + void ClearFun(); + void ClearConst(); + void ClearInfixOprt(); + void ClearPostfixOprt(); + void ClearOprt(); + + void RemoveVar(const string_type &a_strVarName); + const varmap_type& GetUsedVar() const; + const varmap_type& GetVar() const; + const valmap_type& GetConst() const; + const string_type& GetExpr() const; + const funmap_type& GetFunDef() const; + string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; + + const char_type ** GetOprtDef() const; + void DefineNameChars(const char_type *a_szCharset); + void DefineOprtChars(const char_type *a_szCharset); + void DefineInfixOprtChars(const char_type *a_szCharset); + + const char_type* ValidNameChars() const; + const char_type* ValidOprtChars() const; + const char_type* ValidInfixOprtChars() const; + + void SetArgSep(char_type cArgSep); + char_type GetArgSep() const; + + void Error(EErrorCodes a_iErrc, + int a_iPos = (int)mu::string_type::npos, + const string_type &a_strTok = string_type() ) const; + + protected: + + void Init(); + + virtual void InitCharSets() = 0; + virtual void InitFun() = 0; + virtual void InitConst() = 0; + virtual void InitOprt() = 0; + + virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); + + static const char_type *c_DefaultOprt[]; + static std::locale s_locale; ///< The locale used by the parser + static bool g_DbgDumpCmdCode; + static bool g_DbgDumpStack; + + /** \brief A facet class used to change decimal and thousands separator. */ + template<class TChar> + class change_dec_sep : public std::numpunct<TChar> + { + public: + + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + :std::numpunct<TChar>() + ,m_nGroup(nGroup) + ,m_cDecPoint(cDecSep) + ,m_cThousandsSep(cThousandsSep) + {} + + protected: + + virtual char_type do_decimal_point() const + { + return m_cDecPoint; + } + + virtual char_type do_thousands_sep() const + { + return m_cThousandsSep; + } + + virtual std::string do_grouping() const + { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } + + private: + + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; + }; + + private: + + void Assign(const ParserBase &a_Parser); + void InitTokenReader(); + void ReInit() const; + + void AddCallback( const string_type &a_strName, + const ParserCallback &a_Callback, + funmap_type &a_Storage, + const char_type *a_szCharSet ); + + void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal) const; + void ApplyBinOprt(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal) const; + + void ApplyIfElse(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal) const; + + void ApplyFunc(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal, + int iArgCount) const; + + token_type ApplyStrFunc(const token_type &a_FunTok, + const std::vector<token_type> &a_vArg) const; + + int GetOprtPrecedence(const token_type &a_Tok) const; + EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const; + + void CreateRPN() const; + + value_type ParseString() const; + value_type ParseCmdCode() const; + value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; + + void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; + void CheckOprt(const string_type &a_sName, + const ParserCallback &a_Callback, + const string_type &a_szCharSet) const; + + void StackDump(const ParserStack<token_type > &a_stVal, + const ParserStack<token_type > &a_stOprt) const; + + /** \brief Pointer to the parser function. + + Eval() calls the function whose address is stored there. + */ + mutable ParseFunction m_pParseFormula; + mutable ParserByteCode m_vRPN; ///< The Bytecode class. + mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments + stringbuf_type m_vStringVarBuf; + + std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object. + + funmap_type m_FunDef; ///< Map of function names and pointers. + funmap_type m_PostOprtDef; ///< Postfix operator callbacks + funmap_type m_InfixOprtDef; ///< unary infix operator. + funmap_type m_OprtDef; ///< Binary operator callbacks + valmap_type m_ConstDef; ///< user constants. + strmap_type m_StrVarDef; ///< user defined string constants + varmap_type m_VarDef; ///< user defind variables. + + bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off + + string_type m_sNameChars; ///< Charset for names + string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens + string_type m_sInfixOprtChars; ///< Charset for infix operator tokens + + mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses + + // items merely used for caching state information + mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine + mutable int m_nFinalResultIdx; +}; + +} // namespace mu + +#endif + diff --git a/ThirdParty/MuParser/include/muParserBytecode.h b/ThirdParty/MuParser/include/muParserBytecode.h new file mode 100644 index 0000000000000000000000000000000000000000..33e3c26c0a1cc0dbfb92c751698ae7414b7044d1 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserBytecode.h @@ -0,0 +1,141 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef MU_PARSER_BYTECODE_H +#define MU_PARSER_BYTECODE_H + +#include <cassert> +#include <string> +#include <stack> +#include <vector> + +#include "muParserDef.h" +#include "muParserError.h" +#include "muParserToken.h" + +/** \file + \brief Definition of the parser bytecode class. +*/ + + +namespace mu +{ + struct SToken + { + ECmdCode Cmd; + int StackPos; + + union + { + struct //SValData + { + value_type *ptr; + value_type data; + value_type data2; + } Val; + + struct //SFunData + { + // Note: generic_fun_type is merely a placeholder. The real type could be + // anything between gun_type1 and fun_type9. I can't use a void + // pointer due to constraints in the ANSI standard which allows + // data pointers and function pointers to differ in size. + generic_fun_type ptr; + int argc; + int idx; + } Fun; + + struct //SOprtData + { + value_type *ptr; + int offset; + } Oprt; + }; + }; + + + /** \brief Bytecode implementation of the Math Parser. + + The bytecode contains the formula converted to revers polish notation stored in a continious + memory area. Associated with this data are operator codes, variable pointers, constant + values and function pointers. Those are necessary in order to calculate the result. + All those data items will be casted to the underlying datatype of the bytecode. + + \author (C) 2004-2013 Ingo Berg +*/ +class ParserByteCode +{ +private: + + /** \brief Token type for internal use only. */ + typedef ParserToken<value_type, string_type> token_type; + + /** \brief Token vector for storing the RPN. */ + typedef std::vector<SToken> rpn_type; + + /** \brief Position in the Calculation array. */ + unsigned m_iStackPos; + + /** \brief Maximum size needed for the stack. */ + std::size_t m_iMaxStackSize; + + /** \brief The actual rpn storage. */ + rpn_type m_vRPN; + + bool m_bEnableOptimizer; + + void ConstantFolding(ECmdCode a_Oprt); + +public: + + ParserByteCode(); + ParserByteCode(const ParserByteCode &a_ByteCode); + ParserByteCode& operator=(const ParserByteCode &a_ByteCode); + void Assign(const ParserByteCode &a_ByteCode); + + void AddVar(value_type *a_pVar); + void AddVal(value_type a_fVal); + void AddOp(ECmdCode a_Oprt); + void AddIfElse(ECmdCode a_Oprt); + void AddAssignOp(value_type *a_pVar); + void AddFun(generic_fun_type a_pFun, int a_iArgc); + void AddBulkFun(generic_fun_type a_pFun, int a_iArgc); + void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); + + void EnableOptimizer(bool bStat); + + void Finalize(); + void clear(); + std::size_t GetMaxStackSize() const; + std::size_t GetSize() const; + + const SToken* GetBase() const; + void AsciiDump(); +}; + +} // namespace mu + +#endif + + diff --git a/ThirdParty/MuParser/include/muParserCallback.h b/ThirdParty/MuParser/include/muParserCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..578bda0410b9030bfcccb069c8344def8c5501bf --- /dev/null +++ b/ThirdParty/MuParser/include/muParserCallback.h @@ -0,0 +1,118 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_CALLBACK_H +#define MU_PARSER_CALLBACK_H + +#include "muParserDef.h" + +/** \file + \brief Definition of the parser callback class. +*/ + +namespace mu +{ + +/** \brief Encapsulation of prototypes for a numerical parser function. + + Encapsulates the prototyp for numerical parser functions. The class + stores the number of arguments for parser functions as well + as additional flags indication the function is non optimizeable. + The pointer to the callback function pointer is stored as void* + and needs to be casted according to the argument count. + Negative argument counts indicate a parser function with a variable number + of arguments. + + \author (C) 2004-2011 Ingo Berg +*/ +class ParserCallback +{ +public: + ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); + + ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); + + ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(); + ParserCallback(const ParserCallback &a_Fun); + + ParserCallback* Clone() const; + + bool IsOptimizable() const; + void* GetAddr() const; + ECmdCode GetCode() const; + ETypeCode GetType() const; + int GetPri() const; + EOprtAssociativity GetAssociativity() const; + int GetArgc() const; + +private: + void *m_pFun; ///< Pointer to the callback function, casted to void + + /** \brief Number of numeric function arguments + + This number is negative for functions with variable number of arguments. in this cases + they represent the actual number of arguments found. + */ + int m_iArgc; + int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. + EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators + ECmdCode m_iCode; + ETypeCode m_iType; + bool m_bAllowOpti; ///< Flag indication optimizeability +}; + +//------------------------------------------------------------------------------ +/** \brief Container for Callback objects. */ +typedef std::map<string_type, ParserCallback> funmap_type; + +} // namespace mu + +#endif + diff --git a/ThirdParty/MuParser/include/muParserDLL.h b/ThirdParty/MuParser/include/muParserDLL.h new file mode 100644 index 0000000000000000000000000000000000000000..180b4760ed0018426a22903e0521fa38f5976b9d --- /dev/null +++ b/ThirdParty/MuParser/include/muParserDLL.h @@ -0,0 +1,241 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef MU_PARSER_DLL_H +#define MU_PARSER_DLL_H + +#if defined(WIN32) || defined(_WIN32) + #ifdef MUPARSERLIB_EXPORTS + #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl + #else + #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl + #endif +#else + #define API_EXPORT(TYPE) TYPE +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** \file + \brief This file contains the DLL interface of muparser. +*/ + +// Basic types +typedef void* muParserHandle_t; // parser handle + +#ifndef _UNICODE + typedef char muChar_t; // character type +#else + typedef wchar_t muChar_t; // character type +#endif + +typedef int muBool_t; // boolean type +typedef int muInt_t; // integer type +typedef double muFloat_t; // floating point type + +// function types for calculation +typedef muFloat_t (*muFun0_t )(); +typedef muFloat_t (*muFun1_t )(muFloat_t); +typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); +typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + +// Function prototypes for bulkmode functions +typedef muFloat_t (*muBulkFun0_t )(int, int); +typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); +typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + +typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t); +typedef muFloat_t (*muStrFun1_t)(const muChar_t*); +typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t); +typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t); + +// Functions for parser management +typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler +typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables +typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks + +//----------------------------------------------------------------------------------------------------- +// Constants +static const int muOPRT_ASCT_LEFT = 0; +static const int muOPRT_ASCT_RIGHT = 1; + +static const int muBASETYPE_FLOAT = 0; +static const int muBASETYPE_INT = 1; + +//----------------------------------------------------------------------------------------------------- +// +// +// muParser C compatible bindings +// +// +//----------------------------------------------------------------------------------------------------- + + +// Basic operations / initialization +API_EXPORT(muParserHandle_t) mupCreate(int nBaseType); +API_EXPORT(void) mupRelease(muParserHandle_t a_hParser); +API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser); +API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr); +API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData); +API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser); +API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); +API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); +API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize); + +// Defining callbacks / variables / constants +API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize); + +// Defining bulkmode functions +API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun); +API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun); +API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun); +API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun); +API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun); +API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun); +API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun); +API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun); +API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun); +API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun); +API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun); + +// string functions +API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); +API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun); +API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun); + +API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muMultFun_t a_pFun, + muBool_t a_bOptimize); + +API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun2_t a_pFun, + muInt_t a_nPrec, + muInt_t a_nOprtAsct, + muBool_t a_bOptimize); + +API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t a_fVal ); + +API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, + const muChar_t* a_szName, + const muChar_t *a_sVal ); + +API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t *a_fVar); + +API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t *a_fVar); + +API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + muBool_t a_bOptimize); + + +API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + muBool_t a_bOptimize); + +// Define character sets for identifiers +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); + +// Remove all / single variables +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName); +API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser); +API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser); +API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser); +API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); + +// Querying variables / expression variables / constants +API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); +API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser); +API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser); +API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); +API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); +API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar); +API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); +API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); +API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); +API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser); + +// Add value recognition callbacks +API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t); + +// Error handling +API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser); +API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser); +API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler); +API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser); +API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser); +API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser); +API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser); +//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); + +// This is used for .NET only. It creates a new variable allowing the dll to +// manage the variable rather than the .NET garbage collector. +API_EXPORT(muFloat_t*) mupCreateVar(); +API_EXPORT(void) mupReleaseVar(muFloat_t*); + +#ifdef __cplusplus +} +#endif + +#endif // include guard diff --git a/ThirdParty/MuParser/include/muParserDef.h b/ThirdParty/MuParser/include/muParserDef.h new file mode 100644 index 0000000000000000000000000000000000000000..c8e3f930b02311bb40c2b8d382d951387e1be37a --- /dev/null +++ b/ThirdParty/MuParser/include/muParserDef.h @@ -0,0 +1,368 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2014 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef MUP_DEF_H +#define MUP_DEF_H + +#include <iostream> +#include <string> +#include <sstream> +#include <map> + +#include "muParserFixes.h" + +/** \file + \brief This file contains standard definitions used by the parser. +*/ + +#define MUP_VERSION _T("2.2.5") +#define MUP_VERSION_DATE _T("20150427; GC") + +#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */ +//#define MUP_MATH_EXCEPTIONS + +/** \brief Define the base datatype for values. + + This datatype must be a built in value type. You can not use custom classes. + It should be working with all types except "int"! +*/ +#define MUP_BASETYPE double + +/** \brief Activate this option in order to compile with OpenMP support. + + OpenMP is used only in the bulk mode it may increase the performance a bit. +*/ +//#define MUP_USE_OPENMP + +#if defined(_UNICODE) + /** \brief Definition of the basic parser string type. */ + #define MUP_STRING_TYPE std::wstring + + #if !defined(_T) + #define _T(x) L##x + #endif // not defined _T +#else + #ifndef _T + #define _T(x) x + #endif + + /** \brief Definition of the basic parser string type. */ + #define MUP_STRING_TYPE std::string +#endif + +#if defined(_DEBUG) + /** \brief Debug macro to force an abortion of the programm with a certain message. + */ + #define MUP_FAIL(MSG) \ + { \ + bool MSG=false; \ + assert(MSG); \ + } + + /** \brief An assertion that does not kill the program. + + This macro is neutralised in UNICODE builds. It's + too difficult to translate. + */ + #define MUP_ASSERT(COND) \ + if (!(COND)) \ + { \ + stringstream_type ss; \ + ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ + << __FILE__ << _T(" line ") \ + << __LINE__ << _T("."); \ + throw ParserError( ss.str() ); \ + } +#else + #define MUP_FAIL(MSG) + #define MUP_ASSERT(COND) +#endif + + +namespace mu +{ +#if defined(_UNICODE) + + //------------------------------------------------------------------------------ + /** \brief Encapsulate wcout. */ + inline std::wostream& console() + { + return std::wcout; + } + + /** \brief Encapsulate cin. */ + inline std::wistream& console_in() + { + return std::wcin; + } + +#else + + /** \brief Encapsulate cout. + + Used for supporting UNICODE more easily. + */ + inline std::ostream& console() + { + return std::cout; + } + + /** \brief Encapsulate cin. + + Used for supporting UNICODE more easily. + */ + inline std::istream& console_in() + { + return std::cin; + } + +#endif + + //------------------------------------------------------------------------------ + /** \brief Bytecode values. + + \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! + */ + enum ECmdCode + { + // The following are codes for built in binary operators + // apart from built in operators the user has the opportunity to + // add user defined operators. + cmLE = 0, ///< Operator item: less or equal + cmGE = 1, ///< Operator item: greater or equal + cmNEQ = 2, ///< Operator item: not equal + cmEQ = 3, ///< Operator item: equals + cmLT = 4, ///< Operator item: less than + cmGT = 5, ///< Operator item: greater than + cmADD = 6, ///< Operator item: add + cmSUB = 7, ///< Operator item: subtract + cmMUL = 8, ///< Operator item: multiply + cmDIV = 9, ///< Operator item: division + cmPOW = 10, ///< Operator item: y to the power of ... + cmLAND = 11, + cmLOR = 12, + cmASSIGN = 13, ///< Operator item: Assignment operator + cmBO = 14, ///< Operator item: opening bracket + cmBC = 15, ///< Operator item: closing bracket + cmIF = 16, ///< For use in the ternary if-then-else operator + cmELSE = 17, ///< For use in the ternary if-then-else operator + cmENDIF = 18, ///< For use in the ternary if-then-else operator + cmARG_SEP = 19, ///< function argument separator + cmVAR = 20, ///< variable item + cmVAL = 21, ///< value item + + // For optimization purposes + cmVARPOW2, + cmVARPOW3, + cmVARPOW4, + cmVARMUL, + cmPOW2, + + // operators and functions + cmFUNC, ///< Code for a generic function item + cmFUNC_STR, ///< Code for a function with a string parameter + cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index + cmSTRING, ///< Code for a string token + cmOPRT_BIN, ///< user defined binary operator + cmOPRT_POSTFIX, ///< code for postfix operators + cmOPRT_INFIX, ///< code for infix operators + cmEND, ///< end of formula + cmUNKNOWN ///< uninitialized item + }; + + //------------------------------------------------------------------------------ + /** \brief Types internally used by the parser. + */ + enum ETypeCode + { + tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) + tpDBL = 1, ///< Floating point variables + tpVOID = 2 ///< Undefined type. + }; + + //------------------------------------------------------------------------------ + enum EParserVersionInfo + { + pviBRIEF, + pviFULL + }; + + //------------------------------------------------------------------------------ + /** \brief Parser operator precedence values. */ + enum EOprtAssociativity + { + oaLEFT = 0, + oaRIGHT = 1, + oaNONE = 2 + }; + + //------------------------------------------------------------------------------ + /** \brief Parser operator precedence values. */ + enum EOprtPrecedence + { + // binary operators + prLOR = 1, + prLAND = 2, + prLOGIC = 3, ///< logic operators + prCMP = 4, ///< comparsion operators + prADD_SUB = 5, ///< addition + prMUL_DIV = 6, ///< multiplication/division + prPOW = 7, ///< power operator priority (highest) + + // infix operators + prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator + prPOSTFIX = 6 ///< Postfix operator priority (currently unused) + }; + + //------------------------------------------------------------------------------ + // basic types + + /** \brief The numeric datatype used by the parser. + + Normally this is a floating point type either single or double precision. + */ + typedef MUP_BASETYPE value_type; + + /** \brief The stringtype used by the parser. + + Depends on wether UNICODE is used or not. + */ + typedef MUP_STRING_TYPE string_type; + + /** \brief The character type used by the parser. + + Depends on wether UNICODE is used or not. + */ + typedef string_type::value_type char_type; + + /** \brief Typedef for easily using stringstream that respect the parser stringtype. */ + typedef std::basic_stringstream<char_type, + std::char_traits<char_type>, + std::allocator<char_type> > stringstream_type; + + // Data container types + + /** \brief Type used for storing variables. */ + typedef std::map<string_type, value_type*> varmap_type; + + /** \brief Type used for storing constants. */ + typedef std::map<string_type, value_type> valmap_type; + + /** \brief Type for assigning a string name to an index in the internal string table. */ + typedef std::map<string_type, std::size_t> strmap_type; + + // Parser callbacks + + /** \brief Callback type used for functions without arguments. */ + typedef value_type (*generic_fun_type)(); + + /** \brief Callback type used for functions without arguments. */ + typedef value_type (*fun_type0)(); + + /** \brief Callback type used for functions with a single arguments. */ + typedef value_type (*fun_type1)(value_type); + + /** \brief Callback type used for functions with two arguments. */ + typedef value_type (*fun_type2)(value_type, value_type); + + /** \brief Callback type used for functions with three arguments. */ + typedef value_type (*fun_type3)(value_type, value_type, value_type); + + /** \brief Callback type used for functions with four arguments. */ + typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions without arguments. */ + typedef value_type (*bulkfun_type0)(int, int); + + /** \brief Callback type used for functions with a single arguments. */ + typedef value_type (*bulkfun_type1)(int, int, value_type); + + /** \brief Callback type used for functions with two arguments. */ + typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); + + /** \brief Callback type used for functions with three arguments. */ + typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); + + /** \brief Callback type used for functions with four arguments. */ + typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with a variable argument list. */ + typedef value_type (*multfun_type)(const value_type*, int); + + /** \brief Callback type used for functions taking a string as an argument. */ + typedef value_type (*strfun_type1)(const char_type*); + + /** \brief Callback type used for functions taking a string and a value as arguments. */ + typedef value_type (*strfun_type2)(const char_type*, value_type); + + /** \brief Callback type used for functions taking a string and two values as arguments. */ + typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); + + /** \brief Callback used for functions that identify values in a string. */ + typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); + + /** \brief Callback used for variable creation factory functions. */ + typedef value_type* (*facfun_type)(const char_type*, void*); +} // end of namespace + +#endif + diff --git a/ThirdParty/MuParser/include/muParserError.h b/ThirdParty/MuParser/include/muParserError.h new file mode 100644 index 0000000000000000000000000000000000000000..7be257608ca1acaa1fee886fa3c6e409c579ce5b --- /dev/null +++ b/ThirdParty/MuParser/include/muParserError.h @@ -0,0 +1,176 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_ERROR_H +#define MU_PARSER_ERROR_H + +#include <cassert> +#include <stdexcept> +#include <string> +#include <sstream> +#include <vector> +#include <memory> + +#include "muParserDef.h" + +/** \file + \brief This file defines the error class used by the parser. +*/ + +namespace mu +{ + +/** \brief Error codes. */ +enum EErrorCodes +{ + // Formula syntax errors + ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found + ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. + ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") + ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") + ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found + ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found + ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found + ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing + ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position + ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument + ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument + ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") + ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") + ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") + ecTOO_MANY_PARAMS = 14, ///< Too many function parameters + ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") + ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type + ecSTR_RESULT = 17, ///< result is a string + + // Invalid Parser input Parameters + ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. + ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier + ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. + ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. + + ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator + ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer + ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer + ecEMPTY_EXPRESSION = 25, ///< The Expression is empty + ecNAME_CONFLICT = 26, ///< Name conflict + ecOPT_PRI = 27, ///< Invalid operator priority + // + ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) + ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) + ecGENERIC = 30, ///< Generic error + ecLOCALE = 31, ///< Conflict with current locale + + ecUNEXPECTED_CONDITIONAL = 32, + ecMISSING_ELSE_CLAUSE = 33, + ecMISPLACED_COLON = 34, + + ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, + + // internal errors + ecINTERNAL_ERROR = 36, ///< Internal error of any kind. + + // The last two are special entries + ecCOUNT, ///< This is no error code, It just stores just the total number of error codes + ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages +}; + +//--------------------------------------------------------------------------- +/** \brief A class that handles the error messages. +*/ +class ParserErrorMsg +{ +public: + typedef ParserErrorMsg self_type; + + ParserErrorMsg& operator=(const ParserErrorMsg &); + ParserErrorMsg(const ParserErrorMsg&); + ParserErrorMsg(); + + ~ParserErrorMsg(); + + static const ParserErrorMsg& Instance(); + string_type operator[](unsigned a_iIdx) const; + +private: + std::vector<string_type> m_vErrMsg; ///< A vector with the predefined error messages + static const self_type m_Instance; ///< The instance pointer +}; + +//--------------------------------------------------------------------------- +/** \brief Error class of the parser. + \author Ingo Berg + + Part of the math parser package. +*/ +class ParserError +{ +private: + + /** \brief Replace all ocuurences of a substring with another string. */ + void ReplaceSubString( string_type &strSource, + const string_type &strFind, + const string_type &strReplaceWith); + void Reset(); + +public: + + ParserError(); + explicit ParserError(EErrorCodes a_iErrc); + explicit ParserError(const string_type &sMsg); + ParserError( EErrorCodes a_iErrc, + const string_type &sTok, + const string_type &sFormula = string_type(), + int a_iPos = -1); + ParserError( EErrorCodes a_iErrc, + int a_iPos, + const string_type &sTok); + ParserError( const char_type *a_szMsg, + int a_iPos = -1, + const string_type &sTok = string_type()); + ParserError(const ParserError &a_Obj); + ParserError& operator=(const ParserError &a_Obj); + ~ParserError(); + + void SetFormula(const string_type &a_strFormula); + const string_type& GetExpr() const; + const string_type& GetMsg() const; + int GetPos() const; + const string_type& GetToken() const; + EErrorCodes GetCode() const; + +private: + string_type m_strMsg; ///< The message string + string_type m_strFormula; ///< Formula string + string_type m_strTok; ///< Token related with the error + int m_iPos; ///< Formula position related to the error + EErrorCodes m_iErrc; ///< Error code + const ParserErrorMsg &m_ErrMsg; +}; + +} // namespace mu + +#endif + diff --git a/ThirdParty/MuParser/include/muParserFixes.h b/ThirdParty/MuParser/include/muParserFixes.h new file mode 100644 index 0000000000000000000000000000000000000000..0a07237c4c8113f69cf5ffa3d6445fa1fc56d8e0 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserFixes.h @@ -0,0 +1,62 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_FIXES_H +#define MU_PARSER_FIXES_H + +/** \file + \brief This file contains compatibility fixes for some platforms. +*/ + +// +// Compatibility fixes +// + +//--------------------------------------------------------------------------- +// +// Intel Compiler +// +//--------------------------------------------------------------------------- + +#ifdef __INTEL_COMPILER + +// remark #981: operands are evaluated in unspecified order +// disabled -> completely pointless if the functions do not have side effects +// +#pragma warning(disable:981) + +// remark #383: value copied to temporary, reference to temporary used +#pragma warning(disable:383) + +// remark #1572: floating-point equality and inequality comparisons are unreliable +// disabled -> everyone knows it, the parser passes this problem +// deliberately to the user +#pragma warning(disable:1572) + +#endif + +#endif // include guard + + diff --git a/ThirdParty/MuParser/include/muParserInt.h b/ThirdParty/MuParser/include/muParserInt.h new file mode 100644 index 0000000000000000000000000000000000000000..4db2be8b6bd0a70ebdd67b1bc9b8a9519424cba3 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserInt.h @@ -0,0 +1,140 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_INT_H +#define MU_PARSER_INT_H + +#include "muParserBase.h" +#include <vector> + + +/** \file + \brief Definition of a parser using integer value. +*/ + + +namespace mu +{ + +/** \brief Mathematical expressions parser. + + This version of the parser handles only integer numbers. It disables the built in operators thus it is + slower than muParser. Integer values are stored in the double value_type and converted if needed. +*/ +class ParserInt : public ParserBase +{ +private: + static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); }; + + static value_type Abs(value_type); + static value_type Sign(value_type); + static value_type Ite(value_type, value_type, value_type); + // !! The unary Minus is a MUST, otherwise you cant use negative signs !! + static value_type UnaryMinus(value_type); + // Functions with variable number of arguments + static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum + static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum + static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum + // binary operator callbacks + static value_type Add(value_type v1, value_type v2); + static value_type Sub(value_type v1, value_type v2); + static value_type Mul(value_type v1, value_type v2); + static value_type Div(value_type v1, value_type v2); + static value_type Mod(value_type v1, value_type v2); + static value_type Pow(value_type v1, value_type v2); + static value_type Shr(value_type v1, value_type v2); + static value_type Shl(value_type v1, value_type v2); + static value_type LogAnd(value_type v1, value_type v2); + static value_type LogOr(value_type v1, value_type v2); + static value_type And(value_type v1, value_type v2); + static value_type Or(value_type v1, value_type v2); + static value_type Xor(value_type v1, value_type v2); + static value_type Less(value_type v1, value_type v2); + static value_type Greater(value_type v1, value_type v2); + static value_type LessEq(value_type v1, value_type v2); + static value_type GreaterEq(value_type v1, value_type v2); + static value_type Equal(value_type v1, value_type v2); + static value_type NotEqual(value_type v1, value_type v2); + static value_type Not(value_type v1); + + static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); + static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); + static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); + + /** \brief A facet class used to change decimal and thousands separator. */ + template<class TChar> + class change_dec_sep : public std::numpunct<TChar> + { + public: + + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + :std::numpunct<TChar>() + ,m_cDecPoint(cDecSep) + ,m_cThousandsSep(cThousandsSep) + ,m_nGroup(nGroup) + {} + + protected: + + virtual char_type do_decimal_point() const + { + return m_cDecPoint; + } + + virtual char_type do_thousands_sep() const + { + return m_cThousandsSep; + } + + virtual std::string do_grouping() const + { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } + + private: + + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; + }; + +public: + ParserInt(); + + virtual void InitFun(); + virtual void InitOprt(); + virtual void InitConst(); + virtual void InitCharSets(); +}; + +} // namespace mu + +#endif + diff --git a/ThirdParty/MuParser/include/muParserStack.h b/ThirdParty/MuParser/include/muParserStack.h new file mode 100644 index 0000000000000000000000000000000000000000..a4c20a5c8fad254911803a78d7923ac6ebd2da16 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserStack.h @@ -0,0 +1,125 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_STACK_H +#define MU_PARSER_STACK_H + +#include <cassert> +#include <string> +#include <stack> +#include <vector> + +#include "muParserError.h" +#include "muParserToken.h" + +/** \file + \brief This file defines the stack used by muparser. +*/ + +namespace mu +{ + + /** \brief Parser stack implementation. + + Stack implementation based on a std::stack. The behaviour of pop() had been + slightly changed in order to get an error code if the stack is empty. + The stack is used within the Parser both as a value stack and as an operator stack. + + \author (C) 2004-2011 Ingo Berg + */ + template <typename TValueType> + class ParserStack + { + private: + + /** \brief Type of the underlying stack implementation. */ + typedef std::stack<TValueType, std::vector<TValueType> > impl_type; + + impl_type m_Stack; ///< This is the actual stack. + + public: + + //--------------------------------------------------------------------------- + ParserStack() + :m_Stack() + {} + + //--------------------------------------------------------------------------- + virtual ~ParserStack() + {} + + //--------------------------------------------------------------------------- + /** \brief Pop a value from the stack. + + Unlike the standard implementation this function will return the value that + is going to be taken from the stack. + + \throw ParserException in case the stack is empty. + \sa pop(int &a_iErrc) + */ + TValueType pop() + { + if (empty()) + throw ParserError( _T("stack is empty.") ); + + TValueType el = top(); + m_Stack.pop(); + return el; + } + + /** \brief Push an object into the stack. + + \param a_Val object to push into the stack. + \throw nothrow + */ + void push(const TValueType& a_Val) + { + m_Stack.push(a_Val); + } + + /** \brief Return the number of stored elements. */ + unsigned size() const + { + return (unsigned)m_Stack.size(); + } + + /** \brief Returns true if stack is empty false otherwise. */ + bool empty() const + { + return m_Stack.empty(); + } + + /** \brief Return reference to the top object in the stack. + + The top object is the one pushed most recently. + */ + TValueType& top() + { + return m_Stack.top(); + } + }; +} // namespace MathUtils + +#endif diff --git a/ThirdParty/MuParser/include/muParserTemplateMagic.h b/ThirdParty/MuParser/include/muParserTemplateMagic.h new file mode 100644 index 0000000000000000000000000000000000000000..1caeb4b6de47a3daf5d030deaf671988ca174af1 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserTemplateMagic.h @@ -0,0 +1,113 @@ +#ifndef MU_PARSER_TEMPLATE_MAGIC_H +#define MU_PARSER_TEMPLATE_MAGIC_H + +#include <cmath> +#include "muParserError.h" + + +namespace mu +{ + //----------------------------------------------------------------------------------------------- + // + // Compile time type detection + // + //----------------------------------------------------------------------------------------------- + + /** \brief A class singling out integer types at compile time using + template meta programming. + */ + template<typename T> + struct TypeInfo + { + static bool IsInteger() { return false; } + }; + + template<> + struct TypeInfo<char> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<short> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<int> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<long> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<unsigned char> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<unsigned short> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<unsigned int> + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo<unsigned long> + { + static bool IsInteger() { return true; } + }; + + + //----------------------------------------------------------------------------------------------- + // + // Standard math functions with dummy overload for integer types + // + //----------------------------------------------------------------------------------------------- + + /** \brief A template class for providing wrappers for essential math functions. + + This template is spezialized for several types in order to provide a unified interface + for parser internal math function calls regardless of the data type. + */ + template<typename T> + struct MathImpl + { + static T Sin(T v) { return sin(v); } + static T Cos(T v) { return cos(v); } + static T Tan(T v) { return tan(v); } + static T ASin(T v) { return asin(v); } + static T ACos(T v) { return acos(v); } + static T ATan(T v) { return atan(v); } + static T ATan2(T v1, T v2) { return atan2(v1, v2); } + static T Sinh(T v) { return sinh(v); } + static T Cosh(T v) { return cosh(v); } + static T Tanh(T v) { return tanh(v); } + static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } + static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } + static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } + static T Log(T v) { return log(v); } + static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2 + static T Log10(T v) { return log10(v); } // Logarithm base 10 + static T Exp(T v) { return exp(v); } + static T Abs(T v) { return (v>=0) ? v : -v; } + static T Sqrt(T v) { return sqrt(v); } + static T Rint(T v) { return floor(v + (T)0.5); } + static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); } + static T Pow(T v1, T v2) { return std::pow(v1, v2); } + }; +} + +#endif diff --git a/ThirdParty/MuParser/include/muParserTest.h b/ThirdParty/MuParser/include/muParserTest.h new file mode 100644 index 0000000000000000000000000000000000000000..e8da872c557c5f7c2921f1fe7a2bcbc7835885c5 --- /dev/null +++ b/ThirdParty/MuParser/include/muParserTest.h @@ -0,0 +1,214 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_TEST_H +#define MU_PARSER_TEST_H + +#include <string> +#include <cstdlib> +#include <numeric> // for accumulate +#include "muParser.h" +#include "muParserInt.h" + +/** \file + \brief This file contains the parser test class. +*/ + +namespace mu +{ + /** \brief Namespace for test cases. */ + namespace Test + { + //------------------------------------------------------------------------------ + /** \brief Test cases for unit testing. + + (C) 2004-2011 Ingo Berg + */ + class ParserTester // final + { + private: + static int c_iCount; + + // Multiarg callbacks + static value_type f1of1(value_type v) { return v;}; + + static value_type f1of2(value_type v, value_type ) {return v;}; + static value_type f2of2(value_type , value_type v) {return v;}; + + static value_type f1of3(value_type v, value_type , value_type ) {return v;}; + static value_type f2of3(value_type , value_type v, value_type ) {return v;}; + static value_type f3of3(value_type , value_type , value_type v) {return v;}; + + static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;} + static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;} + static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;} + static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;} + + static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; } + static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; } + static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; } + static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; } + static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; } + + static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; } + static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; } + + static value_type plus2(value_type v1) { return v1+2; } + static value_type times3(value_type v1) { return v1*3; } + static value_type sqr(value_type v1) { return v1*v1; } + static value_type sign(value_type v) { return -v; } + static value_type add(value_type v1, value_type v2) { return v1+v2; } + static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } + + + static value_type FirstArg(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") ); + + return a_afArg[0]; + } + + static value_type LastArg(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") ); + + return a_afArg[a_iArgc-1]; + } + + static value_type Sum(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type( _T("too few arguments for function sum.") ); + + value_type fRes=0; + for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; + return fRes; + } + + static value_type Rnd(value_type v) + { + return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0))); + } + + static value_type RndWithString(const char_type*) + { + return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) ); + } + + static value_type Ping() + { + return 10; + } + + static value_type ValueOf(const char_type*) + { + return 123; + } + + static value_type StrFun1(const char_type* v1) + { + int val(0); + stringstream_type(v1) >> val; + return (value_type)val; + } + + static value_type StrFun2(const char_type* v1, value_type v2) + { + int val(0); + stringstream_type(v1) >> val; + return (value_type)(val + v2); + } + + static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) + { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3; + } + + static value_type StrToFloat(const char_type* a_szMsg) + { + value_type val(0); + stringstream_type(a_szMsg) >> val; + return val; + } + + // postfix operator callback + static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } + static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } + static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } + + // Custom value recognition + static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal); + + int TestNames(); + int TestSyntax(); + int TestMultiArg(); + int TestPostFix(); + int TestExpression(); + int TestInfixOprt(); + int TestBinOprt(); + int TestVarConst(); + int TestInterface(); + int TestException(); + int TestStrArg(); + int TestIfThenElse(); + int TestBulkMode(); + + void Abort() const; + + public: + typedef int (ParserTester::*testfun_type)(); + + ParserTester(); + void Run(); + + private: + std::vector<testfun_type> m_vTestFun; + void AddTest(testfun_type a_pFun); + + // Test Double Parser + int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass); + int EqnTestWithVarChange(const string_type& a_str, + double a_fRes1, + double a_fVar1, + double a_fRes2, + double a_fVar2); + int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); + + // Test Int Parser + int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); + + // Test Bulkmode + int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); + }; + } // namespace Test +} // namespace mu + +#endif + + diff --git a/ThirdParty/MuParser/include/muParserToken.h b/ThirdParty/MuParser/include/muParserToken.h new file mode 100644 index 0000000000000000000000000000000000000000..ff48bce7fc5c16505507513c00c0f51eba3e66ce --- /dev/null +++ b/ThirdParty/MuParser/include/muParserToken.h @@ -0,0 +1,401 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_TOKEN_H +#define MU_PARSER_TOKEN_H + +#include <cassert> +#include <string> +#include <stack> +#include <vector> +#include <memory> + +#include "muParserError.h" +#include "muParserCallback.h" + +/** \file + \brief This file contains the parser token definition. +*/ + +namespace mu +{ + /** \brief Encapsulation of the data for a single formula token. + + Formula token implementation. Part of the Math Parser Package. + Formula tokens can be either one of the following: + <ul> + <li>value</li> + <li>variable</li> + <li>function with numerical arguments</li> + <li>functions with a string as argument</li> + <li>prefix operators</li> + <li>infix operators</li> + <li>binary operator</li> + </ul> + + \author (C) 2004-2013 Ingo Berg + */ + template<typename TBase, typename TString> + class ParserToken + { + private: + + ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. + ETypeCode m_iType; + void *m_pTok; ///< Stores Token pointer; not applicable for all tokens + int m_iIdx; ///< An otional index to an external buffer storing the token data + TString m_strTok; ///< Token string + TString m_strVal; ///< Value for string variables + value_type m_fVal; ///< the value + std::auto_ptr<ParserCallback> m_pCallback; + + public: + + //--------------------------------------------------------------------------- + /** \brief Constructor (default). + + Sets token to an neutral state of type cmUNKNOWN. + \throw nothrow + \sa ECmdCode + */ + ParserToken() + :m_iCode(cmUNKNOWN) + ,m_iType(tpVOID) + ,m_pTok(0) + ,m_iIdx(-1) + ,m_strTok() + ,m_strVal() + ,m_fVal(0) + ,m_pCallback() + {} + + //------------------------------------------------------------------------------ + /** \brief Create token from another one. + + Implemented by calling Assign(...) + \throw nothrow + \post m_iType==cmUNKNOWN + \sa #Assign + */ + ParserToken(const ParserToken &a_Tok) + { + Assign(a_Tok); + } + + //------------------------------------------------------------------------------ + /** \brief Assignement operator. + + Copy token state from another token and return this. + Implemented by calling Assign(...). + \throw nothrow + */ + ParserToken& operator=(const ParserToken &a_Tok) + { + Assign(a_Tok); + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Copy token information from argument. + + \throw nothrow + */ + void Assign(const ParserToken &a_Tok) + { + m_iCode = a_Tok.m_iCode; + m_pTok = a_Tok.m_pTok; + m_strTok = a_Tok.m_strTok; + m_iIdx = a_Tok.m_iIdx; + m_strVal = a_Tok.m_strVal; + m_iType = a_Tok.m_iType; + m_fVal = a_Tok.m_fVal; + // create new callback object if a_Tok has one + m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); + } + + //------------------------------------------------------------------------------ + /** \brief Assign a token type. + + Token may not be of type value, variable or function. Those have seperate set functions. + + \pre [assert] a_iType!=cmVAR + \pre [assert] a_iType!=cmVAL + \pre [assert] a_iType!=cmFUNC + \post m_fVal = 0 + \post m_pTok = 0 + */ + ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) + { + // The following types cant be set this way, they have special Set functions + assert(a_iType!=cmVAR); + assert(a_iType!=cmVAL); + assert(a_iType!=cmFUNC); + + m_iCode = a_iType; + m_iType = tpVOID; + m_pTok = 0; + m_strTok = a_strTok; + m_iIdx = -1; + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Set Callback type. */ + ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) + { + assert(a_pCallback.GetAddr()); + + m_iCode = a_pCallback.GetCode(); + m_iType = tpVOID; + m_strTok = a_sTok; + m_pCallback.reset(new ParserCallback(a_pCallback)); + + m_pTok = 0; + m_iIdx = -1; + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Make this token a value token. + + Member variables not necessary for value tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) + { + m_iCode = cmVAL; + m_iType = tpDBL; + m_fVal = a_fVal; + m_strTok = a_strTok; + m_iIdx = -1; + + m_pTok = 0; + m_pCallback.reset(0); + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) + { + m_iCode = cmVAR; + m_iType = tpDBL; + m_strTok = a_strTok; + m_iIdx = -1; + m_pTok = (void*)a_pVar; + m_pCallback.reset(0); + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) + { + m_iCode = cmSTRING; + m_iType = tpSTR; + m_strTok = a_strTok; + m_iIdx = static_cast<int>(a_iSize); + + m_pTok = 0; + m_pCallback.reset(0); + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Set an index associated with the token related data. + + In cmSTRFUNC - This is the index to a string table in the main parser. + \param a_iIdx The index the string function result will take in the bytecode parser. + \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING + */ + void SetIdx(int a_iIdx) + { + if (m_iCode!=cmSTRING || a_iIdx<0) + throw ParserError(ecINTERNAL_ERROR); + + m_iIdx = a_iIdx; + } + + //------------------------------------------------------------------------------ + /** \brief Return Index associated with the token related data. + + In cmSTRFUNC - This is the index to a string table in the main parser. + + \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING + \return The index the result will take in the Bytecode calculatin array (#m_iIdx). + */ + int GetIdx() const + { + if (m_iIdx<0 || m_iCode!=cmSTRING ) + throw ParserError(ecINTERNAL_ERROR); + + return m_iIdx; + } + + //------------------------------------------------------------------------------ + /** \brief Return the token type. + + \return #m_iType + \throw nothrow + */ + ECmdCode GetCode() const + { + if (m_pCallback.get()) + { + return m_pCallback->GetCode(); + } + else + { + return m_iCode; + } + } + + //------------------------------------------------------------------------------ + ETypeCode GetType() const + { + if (m_pCallback.get()) + { + return m_pCallback->GetType(); + } + else + { + return m_iType; + } + } + + //------------------------------------------------------------------------------ + int GetPri() const + { + if ( !m_pCallback.get()) + throw ParserError(ecINTERNAL_ERROR); + + if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetPri(); + } + + //------------------------------------------------------------------------------ + EOprtAssociativity GetAssociativity() const + { + if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetAssociativity(); + } + + //------------------------------------------------------------------------------ + /** \brief Return the address of the callback function assoziated with + function and operator tokens. + + \return The pointer stored in #m_pTok. + \throw exception_type if token type is non of: + <ul> + <li>cmFUNC</li> + <li>cmSTRFUNC</li> + <li>cmPOSTOP</li> + <li>cmINFIXOP</li> + <li>cmOPRT_BIN</li> + </ul> + \sa ECmdCode + */ + generic_fun_type GetFuncAddr() const + { + return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; + } + + //------------------------------------------------------------------------------ + /** \biref Get value of the token. + + Only applicable to variable and value tokens. + \throw exception_type if token is no value/variable token. + */ + TBase GetVal() const + { + switch (m_iCode) + { + case cmVAL: return m_fVal; + case cmVAR: return *((TBase*)m_pTok); + default: throw ParserError(ecVAL_EXPECTED); + } + } + + //------------------------------------------------------------------------------ + /** \brief Get address of a variable token. + + Valid only if m_iType==CmdVar. + \throw exception_type if token is no variable token. + */ + TBase* GetVar() const + { + if (m_iCode!=cmVAR) + throw ParserError(ecINTERNAL_ERROR); + + return (TBase*)m_pTok; + } + + //------------------------------------------------------------------------------ + /** \brief Return the number of function arguments. + + Valid only if m_iType==CmdFUNC. + */ + int GetArgCount() const + { + assert(m_pCallback.get()); + + if (!m_pCallback->GetAddr()) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetArgc(); + } + + //------------------------------------------------------------------------------ + /** \brief Return the token identifier. + + If #m_iType is cmSTRING the token identifier is the value of the string argument + for a string function. + \return #m_strTok + \throw nothrow + \sa m_strTok + */ + const TString& GetAsString() const + { + return m_strTok; + } + }; +} // namespace mu + +#endif diff --git a/ThirdParty/MuParser/include/muParserTokenReader.h b/ThirdParty/MuParser/include/muParserTokenReader.h new file mode 100644 index 0000000000000000000000000000000000000000..654b597693a0f106e2eb12631adac486c05e455a --- /dev/null +++ b/ThirdParty/MuParser/include/muParserTokenReader.h @@ -0,0 +1,161 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MU_PARSER_TOKEN_READER_H +#define MU_PARSER_TOKEN_READER_H + +#include <cassert> +#include <cstdio> +#include <cstring> +#include <list> +#include <map> +#include <memory> +#include <stack> +#include <string> + +#include "muParserDef.h" +#include "muParserToken.h" + +/** \file + \brief This file contains the parser token reader definition. +*/ + + +namespace mu +{ + // Forward declaration + class ParserBase; + + /** \brief Token reader for the ParserBase class. + + */ + class ParserTokenReader + { + private: + + typedef ParserToken<value_type, string_type> token_type; + + public: + + ParserTokenReader(ParserBase *a_pParent); + ParserTokenReader* Clone(ParserBase *a_pParent) const; + + void AddValIdent(identfun_type a_pCallback); + void SetVarCreator(facfun_type a_pFactory, void *pUserData); + void SetFormula(const string_type &a_strFormula); + void SetArgSep(char_type cArgSep); + + int GetPos() const; + const string_type& GetExpr() const; + varmap_type& GetUsedVar(); + char_type GetArgSep() const; + + void IgnoreUndefVar(bool bIgnore); + void ReInit(); + token_type ReadNextToken(); + + private: + + /** \brief Syntax codes. + + The syntax codes control the syntax check done during the first time parsing of + the expression string. They are flags that indicate which tokens are allowed next + if certain tokens are identified. + */ + enum ESynCodes + { + noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" + noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" + noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" + noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" + noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ... + noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" + noOPT = 1 << 6, ///< to avoid i.e. "(+)" + noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" + noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" + noEND = 1 << 9, ///< to avoid unexpected end of formula + noSTR = 1 << 10, ///< to block numeric arguments on string functions + noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7" + noIF = 1 << 12, + noELSE = 1 << 13, + sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, + noANY = ~0 ///< All of he above flags set + }; + + ParserTokenReader(const ParserTokenReader &a_Reader); + ParserTokenReader& operator=(const ParserTokenReader &a_Reader); + void Assign(const ParserTokenReader &a_Reader); + + void SetParent(ParserBase *a_pParent); + int ExtractToken(const char_type *a_szCharSet, + string_type &a_strTok, + int a_iPos) const; + int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const; + + bool IsBuiltIn(token_type &a_Tok); + bool IsArgSep(token_type &a_Tok); + bool IsEOF(token_type &a_Tok); + bool IsInfixOpTok(token_type &a_Tok); + bool IsFunTok(token_type &a_Tok); + bool IsPostOpTok(token_type &a_Tok); + bool IsOprt(token_type &a_Tok); + bool IsValTok(token_type &a_Tok); + bool IsVarTok(token_type &a_Tok); + bool IsStrVarTok(token_type &a_Tok); + bool IsUndefVarTok(token_type &a_Tok); + bool IsString(token_type &a_Tok); + void Error(EErrorCodes a_iErrc, + int a_iPos = -1, + const string_type &a_sTok = string_type() ) const; + + token_type& SaveBeforeReturn(const token_type &tok); + + ParserBase *m_pParser; + string_type m_strFormula; + int m_iPos; + int m_iSynFlags; + bool m_bIgnoreUndefVar; + + const funmap_type *m_pFunDef; + const funmap_type *m_pPostOprtDef; + const funmap_type *m_pInfixOprtDef; + const funmap_type *m_pOprtDef; + const valmap_type *m_pConstDef; + const strmap_type *m_pStrVarDef; + varmap_type *m_pVarDef; ///< The only non const pointer to parser internals + facfun_type m_pFactory; + void *m_pFactoryData; + std::list<identfun_type> m_vIdentFun; ///< Value token identification function + varmap_type m_UsedVar; + value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables + int m_iBrackets; + token_type m_lastTok; + char_type m_cArgSep; ///< The character used for separating function arguments + }; +} // namespace mu + +#endif + + diff --git a/ThirdParty/MuParser/src/muParser.cpp b/ThirdParty/MuParser/src/muParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b536556b6f2dc2c699dd1cb331ba80d9dafd8981 --- /dev/null +++ b/ThirdParty/MuParser/src/muParser.cpp @@ -0,0 +1,397 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "muParser.h" +#include "muParserTemplateMagic.h" + +//--- Standard includes ------------------------------------------------------------------------ +#include <cmath> +#include <algorithm> +#include <numeric> + +/** \brief Pi (what else?). */ +#define PARSER_CONST_PI 3.141592653589793238462643 + +/** \brief The Eulerian number. */ +#define PARSER_CONST_E 2.718281828459045235360287 + +using namespace std; + +/** \file + \brief Implementation of the standard floating point parser. +*/ + + + +/** \brief Namespace for mathematical applications. */ +namespace mu +{ + + + //--------------------------------------------------------------------------- + // Trigonometric function + value_type Parser::Sin(value_type v) { return MathImpl<value_type>::Sin(v); } + value_type Parser::Cos(value_type v) { return MathImpl<value_type>::Cos(v); } + value_type Parser::Tan(value_type v) { return MathImpl<value_type>::Tan(v); } + value_type Parser::ASin(value_type v) { return MathImpl<value_type>::ASin(v); } + value_type Parser::ACos(value_type v) { return MathImpl<value_type>::ACos(v); } + value_type Parser::ATan(value_type v) { return MathImpl<value_type>::ATan(v); } + value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); } + value_type Parser::Sinh(value_type v) { return MathImpl<value_type>::Sinh(v); } + value_type Parser::Cosh(value_type v) { return MathImpl<value_type>::Cosh(v); } + value_type Parser::Tanh(value_type v) { return MathImpl<value_type>::Tanh(v); } + value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); } + value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); } + value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); } + + //--------------------------------------------------------------------------- + // Logarithm functions + + // Logarithm base 2 + value_type Parser::Log2(value_type v) + { + #ifdef MUP_MATH_EXCEPTIONS + if (v<=0) + throw ParserError(ecDOMAIN_ERROR, _T("Log2")); + #endif + + return MathImpl<value_type>::Log2(v); + } + + // Logarithm base 10 + value_type Parser::Log10(value_type v) + { + #ifdef MUP_MATH_EXCEPTIONS + if (v<=0) + throw ParserError(ecDOMAIN_ERROR, _T("Log10")); + #endif + + return MathImpl<value_type>::Log10(v); + } + +// Logarithm base e (natural logarithm) + value_type Parser::Ln(value_type v) + { + #ifdef MUP_MATH_EXCEPTIONS + if (v<=0) + throw ParserError(ecDOMAIN_ERROR, _T("Ln")); + #endif + + return MathImpl<value_type>::Log(v); + } + + //--------------------------------------------------------------------------- + // misc + value_type Parser::Exp(value_type v) { return MathImpl<value_type>::Exp(v); } + value_type Parser::Abs(value_type v) { return MathImpl<value_type>::Abs(v); } + value_type Parser::Sqrt(value_type v) + { + #ifdef MUP_MATH_EXCEPTIONS + if (v<0) + throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); + #endif + + return MathImpl<value_type>::Sqrt(v); + } + value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); } + value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); } + + //--------------------------------------------------------------------------- + /** \brief Callback for the unary minus operator. + \param v The value to negate + \return -v + */ + value_type Parser::UnaryMinus(value_type v) + { + return -v; + } + + //--------------------------------------------------------------------------- + /** \brief Callback for the unary minus operator. + \param v The value to negate + \return -v + */ + value_type Parser::UnaryPlus(value_type v) + { + return v; + } + + //--------------------------------------------------------------------------- + /** \brief Callback for adding multiple values. + \param [in] a_afArg Vector with the function arguments + \param [in] a_iArgc The size of a_afArg + */ + value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw exception_type(_T("too few arguments for function sum.")); + + value_type fRes=0; + for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; + return fRes; + } + + //--------------------------------------------------------------------------- + /** \brief Callback for averaging multiple values. + \param [in] a_afArg Vector with the function arguments + \param [in] a_iArgc The size of a_afArg + */ + value_type Parser::Avg(const value_type *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw exception_type(_T("too few arguments for function sum.")); + + value_type fRes=0; + for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; + return fRes/(value_type)a_iArgc; + } + + + //--------------------------------------------------------------------------- + /** \brief Callback for determining the minimum value out of a vector. + \param [in] a_afArg Vector with the function arguments + \param [in] a_iArgc The size of a_afArg + */ + value_type Parser::Min(const value_type *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw exception_type(_T("too few arguments for function min.")); + + value_type fRes=a_afArg[0]; + for (int i=0; i<a_iArgc; ++i) + fRes = std::min(fRes, a_afArg[i]); + + return fRes; + } + + + //--------------------------------------------------------------------------- + /** \brief Callback for determining the maximum value out of a vector. + \param [in] a_afArg Vector with the function arguments + \param [in] a_iArgc The size of a_afArg + */ + value_type Parser::Max(const value_type *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw exception_type(_T("too few arguments for function min.")); + + value_type fRes=a_afArg[0]; + for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]); + + return fRes; + } + + + //--------------------------------------------------------------------------- + /** \brief Default value recognition callback. + \param [in] a_szExpr Pointer to the expression + \param [in, out] a_iPos Pointer to an index storing the current position within the expression + \param [out] a_fVal Pointer where the value should be stored in case one is found. + \return 1 if a value was found 0 otherwise. + */ + int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal) + { + value_type fVal(0); + + stringstream_type stream(a_szExpr); + stream.seekg(0); // todo: check if this really is necessary + stream.imbue(Parser::s_locale); + stream >> fVal; + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + + if (iEnd==(stringstream_type::pos_type)-1) + return 0; + + *a_iPos += (int)iEnd; + *a_fVal = fVal; + return 1; + } + + + //--------------------------------------------------------------------------- + /** \brief Constructor. + + Call ParserBase class constructor and trigger Function, Operator and Constant initialization. + */ + Parser::Parser() + :ParserBase() + { + AddValIdent(IsVal); + + InitCharSets(); + InitFun(); + InitConst(); + InitOprt(); + } + + //--------------------------------------------------------------------------- + /** \brief Define the character sets. + \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars + + This function is used for initializing the default character sets that define + the characters to be useable in function and variable names and operators. + */ + void Parser::InitCharSets() + { + DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); + DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") ); + DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") ); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize the default functions. */ + void Parser::InitFun() + { + if (mu::TypeInfo<mu::value_type>::IsInteger()) + { + // When setting MUP_BASETYPE to an integer type + // Place functions for dealing with integer values here + // ... + // ... + // ... + } + else + { + // trigonometric functions + DefineFun(_T("sin"), Sin); + DefineFun(_T("cos"), Cos); + DefineFun(_T("tan"), Tan); + // arcus functions + DefineFun(_T("asin"), ASin); + DefineFun(_T("acos"), ACos); + DefineFun(_T("atan"), ATan); + DefineFun(_T("atan2"), ATan2); + // hyperbolic functions + DefineFun(_T("sinh"), Sinh); + DefineFun(_T("cosh"), Cosh); + DefineFun(_T("tanh"), Tanh); + // arcus hyperbolic functions + DefineFun(_T("asinh"), ASinh); + DefineFun(_T("acosh"), ACosh); + DefineFun(_T("atanh"), ATanh); + // Logarithm functions + DefineFun(_T("log2"), Log2); + DefineFun(_T("log10"), Log10); + DefineFun(_T("log"), Ln); + DefineFun(_T("ln"), Ln); + // misc + DefineFun(_T("exp"), Exp); + DefineFun(_T("sqrt"), Sqrt); + DefineFun(_T("sign"), Sign); + DefineFun(_T("rint"), Rint); + DefineFun(_T("abs"), Abs); + // Functions with variable number of arguments + DefineFun(_T("sum"), Sum); + DefineFun(_T("avg"), Avg); + DefineFun(_T("min"), Min); + DefineFun(_T("max"), Max); + } + } + + //--------------------------------------------------------------------------- + /** \brief Initialize constants. + + By default the parser recognizes two constants. Pi ("pi") and the Eulerian + number ("_e"). + */ + void Parser::InitConst() + { + DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); + DefineConst(_T("_e"), (value_type)PARSER_CONST_E); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize operators. + + By default only the unary minus operator is added. + */ + void Parser::InitOprt() + { + DefineInfixOprt(_T("-"), UnaryMinus); + DefineInfixOprt(_T("+"), UnaryPlus); + } + + //--------------------------------------------------------------------------- + void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) + { + // this is just sample code to illustrate modifying variable names on the fly. + // I'm not sure anyone really needs such a feature... + /* + + + string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); + string sRepl = std::string("_") + sVar + "_"; + + int nOrigVarEnd = nEnd; + cout << "variable detected!\n"; + cout << " Expr: " << *pExpr << "\n"; + cout << " Start: " << nStart << "\n"; + cout << " End: " << nEnd << "\n"; + cout << " Var: \"" << sVar << "\"\n"; + cout << " Repl: \"" << sRepl << "\"\n"; + nEnd = nStart + sRepl.length(); + cout << " End: " << nEnd << "\n"; + pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); + cout << " New expr: " << *pExpr << "\n"; + */ + } + + //--------------------------------------------------------------------------- + /** \brief Numerically differentiate with regard to a variable. + \param [in] a_Var Pointer to the differentiation variable. + \param [in] a_fPos Position at which the differentiation should take place. + \param [in] a_fEpsilon Epsilon used for the numerical differentiation. + + Numerical differentiation uses a 5 point operator yielding a 4th order + formula. The default value for epsilon is 0.00074 which is + numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser + forum: + + http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 + */ + value_type Parser::Diff(value_type *a_Var, + value_type a_fPos, + value_type a_fEpsilon) const + { + value_type fRes(0), + fBuf(*a_Var), + f[4] = {0,0,0,0}, + fEpsilon(a_fEpsilon); + + // Backwards compatible calculation of epsilon inc case the user doesn't provide + // his own epsilon + if (fEpsilon==0) + fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; + + *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval(); + *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval(); + *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval(); + *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval(); + *a_Var = fBuf; // restore variable + + fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon); + return fRes; + } +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserBase.cpp b/ThirdParty/MuParser/src/muParserBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdda6041d76a8117f54d4fc0afc8ff6a1030b9c7 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserBase.cpp @@ -0,0 +1,1778 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "muParserBase.h" +#include "muParserTemplateMagic.h" + +//--- Standard includes ------------------------------------------------------------------------ +#include <cassert> +#include <algorithm> +#include <cmath> +#include <memory> +#include <vector> +#include <deque> +#include <sstream> +#include <locale> + +#ifdef MUP_USE_OPENMP + #include <omp.h> +#endif + +using namespace std; + +/** \file + \brief This file contains the basic implementation of the muparser engine. +*/ + +namespace mu +{ + std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.')); + + bool ParserBase::g_DbgDumpCmdCode = false; + bool ParserBase::g_DbgDumpStack = false; + + //------------------------------------------------------------------------------ + /** \brief Identifiers for built in binary operators. + + When defining custom binary operators with #AddOprt(...) make sure not to choose + names conflicting with these definitions. + */ + const char_type* ParserBase::c_DefaultOprt[] = + { + _T("<="), _T(">="), _T("!="), + _T("=="), _T("<"), _T(">"), + _T("+"), _T("-"), _T("*"), + _T("/"), _T("^"), _T("&&"), + _T("||"), _T("="), _T("("), + _T(")"), _T("?"), _T(":"), 0 + }; + + //------------------------------------------------------------------------------ + /** \brief Constructor. + \param a_szFormula the formula to interpret. + \throw ParserException if a_szFormula is null. + */ + ParserBase::ParserBase() + :m_pParseFormula(&ParserBase::ParseString) + ,m_vRPN() + ,m_vStringBuf() + ,m_pTokenReader() + ,m_FunDef() + ,m_PostOprtDef() + ,m_InfixOprtDef() + ,m_OprtDef() + ,m_ConstDef() + ,m_StrVarDef() + ,m_VarDef() + ,m_bBuiltInOp(true) + ,m_sNameChars() + ,m_sOprtChars() + ,m_sInfixOprtChars() + ,m_nIfElseCounter(0) + ,m_vStackBuffer() + ,m_nFinalResultIdx(0) + { + InitTokenReader(); + } + + //--------------------------------------------------------------------------- + /** \brief Copy constructor. + + The parser can be safely copy constructed but the bytecode is reset during + copy construction. + */ + ParserBase::ParserBase(const ParserBase &a_Parser) + :m_pParseFormula(&ParserBase::ParseString) + ,m_vRPN() + ,m_vStringBuf() + ,m_pTokenReader() + ,m_FunDef() + ,m_PostOprtDef() + ,m_InfixOprtDef() + ,m_OprtDef() + ,m_ConstDef() + ,m_StrVarDef() + ,m_VarDef() + ,m_bBuiltInOp(true) + ,m_sNameChars() + ,m_sOprtChars() + ,m_sInfixOprtChars() + ,m_nIfElseCounter(0) + { + m_pTokenReader.reset(new token_reader_type(this)); + Assign(a_Parser); + } + + //--------------------------------------------------------------------------- + ParserBase::~ParserBase() + {} + + //--------------------------------------------------------------------------- + /** \brief Assignment operator. + + Implemented by calling Assign(a_Parser). Self assignment is suppressed. + \param a_Parser Object to copy to this. + \return *this + \throw nothrow + */ + ParserBase& ParserBase::operator=(const ParserBase &a_Parser) + { + Assign(a_Parser); + return *this; + } + + //--------------------------------------------------------------------------- + /** \brief Copy state of a parser object to this. + + Clears Variables and Functions of this parser. + Copies the states of all internal variables. + Resets parse function to string parse mode. + + \param a_Parser the source object. + */ + void ParserBase::Assign(const ParserBase &a_Parser) + { + if (&a_Parser==this) + return; + + // Don't copy bytecode instead cause the parser to create new bytecode + // by resetting the parse function. + ReInit(); + + m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants + m_VarDef = a_Parser.m_VarDef; // Copy user defined variables + m_bBuiltInOp = a_Parser.m_bBuiltInOp; + m_vStringBuf = a_Parser.m_vStringBuf; + m_vStackBuffer = a_Parser.m_vStackBuffer; + m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; + m_StrVarDef = a_Parser.m_StrVarDef; + m_vStringVarBuf = a_Parser.m_vStringVarBuf; + m_nIfElseCounter = a_Parser.m_nIfElseCounter; + m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); + + // Copy function and operator callbacks + m_FunDef = a_Parser.m_FunDef; // Copy function definitions + m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators + m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation + m_OprtDef = a_Parser.m_OprtDef; // binary operators + + m_sNameChars = a_Parser.m_sNameChars; + m_sOprtChars = a_Parser.m_sOprtChars; + m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; + } + + //--------------------------------------------------------------------------- + /** \brief Set the decimal separator. + \param cDecSep Decimal separator as a character value. + \sa SetThousandsSep + + By default muparser uses the "C" locale. The decimal separator of this + locale is overwritten by the one provided here. + */ + void ParserBase::SetDecSep(char_type cDecSep) + { + char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep(); + s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep)); + } + + //--------------------------------------------------------------------------- + /** \brief Sets the thousands operator. + \param cThousandsSep The thousands separator as a character + \sa SetDecSep + + By default muparser uses the "C" locale. The thousands separator of this + locale is overwritten by the one provided here. + */ + void ParserBase::SetThousandsSep(char_type cThousandsSep) + { + char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point(); + s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep)); + } + + //--------------------------------------------------------------------------- + /** \brief Resets the locale. + + The default locale used "." as decimal separator, no thousands separator and + "," as function argument separator. + */ + void ParserBase::ResetLocale() + { + s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.')); + SetArgSep(','); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize the token reader. + + Create new token reader object and submit pointers to function, operator, + constant and variable definitions. + + \post m_pTokenReader.get()!=0 + \throw nothrow + */ + void ParserBase::InitTokenReader() + { + m_pTokenReader.reset(new token_reader_type(this)); + } + + //--------------------------------------------------------------------------- + /** \brief Reset parser to string parsing mode and clear internal buffers. + + Clear bytecode, reset the token reader. + \throw nothrow + */ + void ParserBase::ReInit() const + { + m_pParseFormula = &ParserBase::ParseString; + m_vStringBuf.clear(); + m_vRPN.clear(); + m_pTokenReader->ReInit(); + m_nIfElseCounter = 0; + } + + //--------------------------------------------------------------------------- + void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) + {} + + //--------------------------------------------------------------------------- + /** \brief Returns the version of muparser. + \param eInfo A flag indicating whether the full version info should be + returned or not. + + Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS + are returned only if eInfo==pviFULL. + */ + string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const + { + stringstream_type ss; + + ss << MUP_VERSION; + + if (eInfo==pviFULL) + { + ss << _T(" (") << MUP_VERSION_DATE; + ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT"); + +#ifdef _DEBUG + ss << _T("; DEBUG"); +#else + ss << _T("; RELEASE"); +#endif + +#ifdef _UNICODE + ss << _T("; UNICODE"); +#else + #ifdef _MBCS + ss << _T("; MBCS"); + #else + ss << _T("; ASCII"); + #endif +#endif + +#ifdef MUP_USE_OPENMP + ss << _T("; OPENMP"); +//#else +// ss << _T("; NO_OPENMP"); +#endif + +#if defined(MUP_MATH_EXCEPTIONS) + ss << _T("; MATHEXC"); +//#else +// ss << _T("; NO_MATHEXC"); +#endif + + ss << _T(")"); + } + + return ss.str(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a value parsing function. + + When parsing an expression muParser tries to detect values in the expression + string using different valident callbacks. Thus it's possible to parse + for hex values, binary values and floating point values. + */ + void ParserBase::AddValIdent(identfun_type a_pCallback) + { + m_pTokenReader->AddValIdent(a_pCallback); + } + + //--------------------------------------------------------------------------- + /** \brief Set a function that can create variable pointer for unknown expression variables. + \param a_pFactory A pointer to the variable factory. + \param pUserData A user defined context pointer. + */ + void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) + { + m_pTokenReader->SetVarCreator(a_pFactory, pUserData); + } + + //--------------------------------------------------------------------------- + /** \brief Add a function or operator callback to the parser. */ + void ParserBase::AddCallback( const string_type &a_strName, + const ParserCallback &a_Callback, + funmap_type &a_Storage, + const char_type *a_szCharSet ) + { + if (a_Callback.GetAddr()==0) + Error(ecINVALID_FUN_PTR); + + const funmap_type *pFunMap = &a_Storage; + + // Check for conflicting operator or function names + if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() ) + Error(ecNAME_CONFLICT, -1, a_strName); + + if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() ) + Error(ecNAME_CONFLICT, -1, a_strName); + + if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() ) + Error(ecNAME_CONFLICT, -1, a_strName); + + if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() ) + Error(ecNAME_CONFLICT, -1, a_strName); + + CheckOprt(a_strName, a_Callback, a_szCharSet); + a_Storage[a_strName] = a_Callback; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Check if a name contains invalid characters. + + \throw ParserException if the name contains invalid characters. + */ + void ParserBase::CheckOprt(const string_type &a_sName, + const ParserCallback &a_Callback, + const string_type &a_szCharSet) const + { + if ( !a_sName.length() || + (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || + (a_sName[0]>='0' && a_sName[0]<='9')) + { + switch(a_Callback.GetCode()) + { + case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); + case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); + default: Error(ecINVALID_NAME, -1, a_sName); + } + } + } + + //--------------------------------------------------------------------------- + /** \brief Check if a name contains invalid characters. + + \throw ParserException if the name contains invalid characters. + */ + void ParserBase::CheckName(const string_type &a_sName, + const string_type &a_szCharSet) const + { + if ( !a_sName.length() || + (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || + (a_sName[0]>='0' && a_sName[0]<='9')) + { + Error(ecINVALID_NAME); + } + } + + //--------------------------------------------------------------------------- + /** \brief Set the formula. + \param a_strFormula Formula as string_type + \throw ParserException in case of syntax errors. + + Triggers first time calculation thus the creation of the bytecode and + scanning of used variables. + */ + void ParserBase::SetExpr(const string_type &a_sExpr) + { + // Check locale compatibility + std::locale loc; + if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point()) + Error(ecLOCALE); + + // <ibg> 20060222: Bugfix for Borland-Kylix: + // adding a space to the expression will keep Borlands KYLIX from going wild + // when calling tellg on a stringstream created from the expression after + // reading a value at the end of an expression. (mu::Parser::IsVal function) + // (tellg returns -1 otherwise causing the parser to ignore the value) + string_type sBuf(a_sExpr + _T(" ") ); + m_pTokenReader->SetFormula(sBuf); + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Get the default symbols used for the built in operators. + \sa c_DefaultOprt + */ + const char_type** ParserBase::GetOprtDef() const + { + return (const char_type **)(&c_DefaultOprt[0]); + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + functions, variables, constants. + */ + void ParserBase::DefineNameChars(const char_type *a_szCharset) + { + m_sNameChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + binary operators and postfix operators. + */ + void ParserBase::DefineOprtChars(const char_type *a_szCharset) + { + m_sOprtChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + infix operators. + */ + void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset) + { + m_sInfixOprtChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in name identifiers. + \sa #ValidOprtChars, #ValidPrefixOprtChars + */ + const char_type* ParserBase::ValidNameChars() const + { + assert(m_sNameChars.size()); + return m_sNameChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in operator definitions. + \sa #ValidNameChars, #ValidPrefixOprtChars + */ + const char_type* ParserBase::ValidOprtChars() const + { + assert(m_sOprtChars.size()); + return m_sOprtChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in infix operator definitions. + \sa #ValidNameChars, #ValidOprtChars + */ + const char_type* ParserBase::ValidInfixOprtChars() const + { + assert(m_sInfixOprtChars.size()); + return m_sInfixOprtChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + */ + void ParserBase::DefinePostfixOprt(const string_type &a_sName, + fun_type1 a_pFun, + bool a_bAllowOpt) + { + AddCallback(a_sName, + ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), + m_PostOprtDef, + ValidOprtChars() ); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize user defined functions. + + Calls the virtual functions InitFun(), InitConst() and InitOprt(). + */ + void ParserBase::Init() + { + InitCharSets(); + InitFun(); + InitConst(); + InitOprt(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + \param [in] a_sName operator Identifier + \param [in] a_pFun Operator callback function + \param [in] a_iPrec Operator Precedence (default=prSIGN) + \param [in] a_bAllowOpt True if operator is volatile (default=false) + \sa EPrec + */ + void ParserBase::DefineInfixOprt(const string_type &a_sName, + fun_type1 a_pFun, + int a_iPrec, + bool a_bAllowOpt) + { + AddCallback(a_sName, + ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), + m_InfixOprtDef, + ValidInfixOprtChars() ); + } + + + //--------------------------------------------------------------------------- + /** \brief Define a binary operator. + \param [in] a_sName The identifier of the operator. + \param [in] a_pFun Pointer to the callback function. + \param [in] a_iPrec Precedence of the operator. + \param [in] a_eAssociativity The associativity of the operator. + \param [in] a_bAllowOpt If this is true the operator may be optimized away. + + Adds a new Binary operator the the parser instance. + */ + void ParserBase::DefineOprt( const string_type &a_sName, + fun_type2 a_pFun, + unsigned a_iPrec, + EOprtAssociativity a_eAssociativity, + bool a_bAllowOpt ) + { + // Check for conflicts with built in operator names + for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i) + if (a_sName == string_type(c_DefaultOprt[i])) + Error(ecBUILTIN_OVERLOAD, -1, a_sName); + + AddCallback(a_sName, + ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), + m_OprtDef, + ValidOprtChars() ); + } + + //--------------------------------------------------------------------------- + /** \brief Define a new string constant. + \param [in] a_strName The name of the constant. + \param [in] a_strVal the value of the constant. + */ + void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal) + { + // Test if a constant with that names already exists + if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end()) + Error(ecNAME_CONFLICT); + + CheckName(a_strName, ValidNameChars()); + + m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer + m_StrVarDef[a_strName] = m_vStringVarBuf.size()-1; // bind buffer index to variable name + + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined variable. + \param [in] a_sName the variable name + \param [in] a_pVar A pointer to the variable value. + \post Will reset the Parser to string parsing mode. + \throw ParserException in case the name contains invalid signs or a_pVar is NULL. + */ + void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar) + { + if (a_pVar==0) + Error(ecINVALID_VAR_PTR); + + // Test if a constant with that names already exists + if (m_ConstDef.find(a_sName)!=m_ConstDef.end()) + Error(ecNAME_CONFLICT); + + CheckName(a_sName, ValidNameChars()); + m_VarDef[a_sName] = a_pVar; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined constant. + \param [in] a_sName The name of the constant. + \param [in] a_fVal the value of the constant. + \post Will reset the Parser to string parsing mode. + \throw ParserException in case the name contains invalid signs. + */ + void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal) + { + CheckName(a_sName, ValidNameChars()); + m_ConstDef[a_sName] = a_fVal; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code + */ + int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const + { + switch (a_Tok.GetCode()) + { + // built in operators + case cmEND: return -5; + case cmARG_SEP: return -4; + case cmASSIGN: return -1; + case cmELSE: + case cmIF: return 0; + case cmLAND: return prLAND; + case cmLOR: return prLOR; + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: return prCMP; + case cmADD: + case cmSUB: return prADD_SUB; + case cmMUL: + case cmDIV: return prMUL_DIV; + case cmPOW: return prPOW; + + // user defined binary operators + case cmOPRT_INFIX: + case cmOPRT_BIN: return a_Tok.GetPri(); + default: Error(ecINTERNAL_ERROR, 5); + return 999; + } + } + + //--------------------------------------------------------------------------- + /** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code + */ + EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const + { + switch (a_Tok.GetCode()) + { + case cmASSIGN: + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: return oaLEFT; + case cmPOW: return oaRIGHT; + case cmOPRT_BIN: return a_Tok.GetAssociativity(); + default: return oaNONE; + } + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing the used variables only. */ + const varmap_type& ParserBase::GetUsedVar() const + { + try + { + m_pTokenReader->IgnoreUndefVar(true); + CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it + // may contain references to nonexisting variables. + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + } + catch(exception_type & /*e*/) + { + // Make sure to stay in string parse mode, dont call ReInit() + // because it deletes the array with the used variables + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + throw; + } + + return m_pTokenReader->GetUsedVar(); + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing the used variables only. */ + const varmap_type& ParserBase::GetVar() const + { + return m_VarDef; + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing all parser constants. */ + const valmap_type& ParserBase::GetConst() const + { + return m_ConstDef; + } + + //--------------------------------------------------------------------------- + /** \brief Return prototypes of all parser functions. + \return #m_FunDef + \sa FunProt + \throw nothrow + + The return type is a map of the public type #funmap_type containing the prototype + definitions for all numerical parser functions. String functions are not part of + this map. The Prototype definition is encapsulated in objects of the class FunProt + one per parser function each associated with function names via a map construct. + */ + const funmap_type& ParserBase::GetFunDef() const + { + return m_FunDef; + } + + //--------------------------------------------------------------------------- + /** \brief Retrieve the formula. */ + const string_type& ParserBase::GetExpr() const + { + return m_pTokenReader->GetExpr(); + } + + //--------------------------------------------------------------------------- + /** \brief Execute a function that takes a single string argument. + \param a_FunTok Function token. + \throw exception_type If the function token is not a string function + */ + ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, + const std::vector<token_type> &a_vArg) const + { + if (a_vArg.back().GetCode()!=cmSTRING) + Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + + token_type valTok; + generic_fun_type pFunc = a_FunTok.GetFuncAddr(); + assert(pFunc); + + try + { + // Check function arguments; write dummy value into valtok to represent the result + switch(a_FunTok.GetArgCount()) + { + case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; + case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; + case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; + default: Error(ecINTERNAL_ERROR); + } + } + catch(ParserError& ) + { + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + } + + // string functions won't be optimized + m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); + + // Push dummy value representing the function result to the stack + return valTok; + } + + //--------------------------------------------------------------------------- + /** \brief Apply a function token. + \param iArgCount Number of Arguments actually gathered used only for multiarg functions. + \post The result is pushed to the value stack + \post The function token is removed from the stack + \throw exception_type if Argument count does not match function requirements. + */ + void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal, + int a_iArgCount) const + { + assert(m_pTokenReader.get()); + + // Operator stack empty or does not contain tokens with callback functions + if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 ) + return; + + token_type funTok = a_stOpt.pop(); + assert(funTok.GetFuncAddr()); + + // Binary operators must rely on their internal operator number + // since counting of operators relies on commas for function arguments + // binary operators do not have commas in their expression + int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; + + // determine how many parameters the function needs. To remember iArgCount includes the + // string parameter whilst GetArgCount() counts only numeric parameters. + int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0); + + // Thats the number of numerical parameters + int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0); + + if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1) + Error(ecINTERNAL_ERROR); + + if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); + + if (funTok.GetCode()!=cmOPRT_BIN && iArgCount<iArgRequired ) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); + + if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired ) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); + + // Collect the numeric function arguments from the value stack and store them + // in a vector + std::vector<token_type> stArg; + for (int i=0; i<iArgNumerical; ++i) + { + stArg.push_back( a_stVal.pop() ); + if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR ) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + } + + switch(funTok.GetCode()) + { + case cmFUNC_STR: + stArg.push_back(a_stVal.pop()); + + if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR ) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + + ApplyStrFunc(funTok, stArg); + break; + + case cmFUNC_BULK: + m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); + break; + + case cmOPRT_BIN: + case cmOPRT_POSTFIX: + case cmOPRT_INFIX: + case cmFUNC: + if (funTok.GetArgCount()==-1 && iArgCount==0) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); + + m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical); + break; + } + + // Push dummy value representing the function result to the stack + token_type token; + token.SetVal(1); + a_stVal.push(token); + } + + //--------------------------------------------------------------------------- + void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal) const + { + // Check if there is an if Else clause to be calculated + while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE) + { + token_type opElse = a_stOpt.pop(); + MUP_ASSERT(a_stOpt.size()>0); + + // Take the value associated with the else branch from the value stack + token_type vVal2 = a_stVal.pop(); + + MUP_ASSERT(a_stOpt.size()>0); + MUP_ASSERT(a_stVal.size()>=2); + + // it then else is a ternary operator Pop all three values from the value s + // tack and just return the right value + token_type vVal1 = a_stVal.pop(); + token_type vExpr = a_stVal.pop(); + + a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2); + + token_type opIf = a_stOpt.pop(); + MUP_ASSERT(opElse.GetCode()==cmELSE); + MUP_ASSERT(opIf.GetCode()==cmIF); + + m_vRPN.AddIfElse(cmENDIF); + } // while pending if-else-clause found + } + + //--------------------------------------------------------------------------- + /** \brief Performs the necessary steps to write code for + the execution of binary operators into the bytecode. + */ + void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt, + ParserStack<token_type> &a_stVal) const + { + // is it a user defined binary operator? + if (a_stOpt.top().GetCode()==cmOPRT_BIN) + { + ApplyFunc(a_stOpt, a_stVal, 2); + } + else + { + MUP_ASSERT(a_stVal.size()>=2); + token_type valTok1 = a_stVal.pop(), + valTok2 = a_stVal.pop(), + optTok = a_stOpt.pop(), + resTok; + + if ( valTok1.GetType()!=valTok2.GetType() || + (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) ) + Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); + + if (optTok.GetCode()==cmASSIGN) + { + if (valTok2.GetCode()!=cmVAR) + Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); + + m_vRPN.AddAssignOp(valTok2.GetVar()); + } + else + m_vRPN.AddOp(optTok.GetCode()); + + resTok.SetVal(1); + a_stVal.push(resTok); + } + } + + //--------------------------------------------------------------------------- + /** \brief Apply a binary operator. + \param a_stOpt The operator stack + \param a_stVal The value stack + */ + void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt, + ParserStack<token_type> &stVal) const + { + while (stOpt.size() && + stOpt.top().GetCode() != cmBO && + stOpt.top().GetCode() != cmIF) + { + token_type tok = stOpt.top(); + switch (tok.GetCode()) + { + case cmOPRT_INFIX: + case cmOPRT_BIN: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmLT: + case cmGT: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmLAND: + case cmLOR: + case cmASSIGN: + if (stOpt.top().GetCode()==cmOPRT_INFIX) + ApplyFunc(stOpt, stVal, 1); + else + ApplyBinOprt(stOpt, stVal); + break; + + case cmELSE: + ApplyIfElse(stOpt, stVal); + break; + + default: + Error(ecINTERNAL_ERROR); + } + } + } + + //--------------------------------------------------------------------------- + /** \brief Parse the command code. + \sa ParseString(...) + + Command code contains precalculated stack positions of the values and the + associated operators. The Stack is filled beginning from index one the + value at index zero is not used at all. + */ + value_type ParserBase::ParseCmdCode() const + { + return ParseCmdCodeBulk(0, 0); + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate the RPN. + \param nOffset The offset added to variable addresses (for bulk mode) + \param nThreadID OpenMP Thread id of the calling thread + */ + value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const + { + assert(nThreadID<=s_MaxNumOpenMPThreads); + + // Note: The check for nOffset==0 and nThreadID here is not necessary but + // brings a minor performance gain when not in bulk mode. + value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; + value_type buf; + int sidx(0); + for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok) + { + switch (pTok->Cmd) + { + // built in binary operators + case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue; + case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue; + case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue; + case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue; + case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue; + case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue; + case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue; + case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue; + case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue; + case cmDIV: --sidx; + + #if defined(MUP_MATH_EXCEPTIONS) + if (Stack[1+sidx]==0) + Error(ecDIV_BY_ZERO); + #endif + Stack[sidx] /= Stack[1+sidx]; + continue; + + case cmPOW: + --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]); + continue; + + case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue; + case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue; + + case cmASSIGN: + // Bugfix for Bulkmode: + // for details see: + // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws + --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue; + // original code: + //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; + + //case cmBO: // unused, listed for compiler optimization purposes + //case cmBC: + // MUP_FAIL(INVALID_CODE_IN_BYTECODE); + // continue; + + case cmIF: + if (Stack[sidx--]==0) + pTok += pTok->Oprt.offset; + continue; + + case cmELSE: + pTok += pTok->Oprt.offset; + continue; + + case cmENDIF: + continue; + + //case cmARG_SEP: + // MUP_FAIL(INVALID_CODE_IN_BYTECODE); + // continue; + + // value and variable tokens + case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue; + case cmVAL: Stack[++sidx] = pTok->Val.data2; continue; + + case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf*buf; + continue; + + case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf*buf*buf; + continue; + + case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf*buf*buf*buf; + continue; + + case cmVARMUL: Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; + continue; + + // Next is treatment of numeric functions + case cmFUNC: + { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch(iArgCount) + { + case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue; + case 1: Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); continue; + case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue; + case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; + case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; + case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; + case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; + case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; + case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; + case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; + case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; + default: + if (iArgCount>0) // function with variable arguments store the number as a negative value + Error(ecINTERNAL_ERROR, 1); + + sidx -= -iArgCount - 1; + Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); + continue; + } + } + + // Next is treatment of string functions + case cmFUNC_STR: + { + sidx -= pTok->Fun.argc -1; + + // The index of the string argument in the string table + int iIdxStack = pTok->Fun.idx; + MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() ); + + switch(pTok->Fun.argc) // switch according to argument count + { + case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue; + case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue; + case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue; + } + + continue; + } + + case cmFUNC_BULK: + { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch(iArgCount) + { + case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID); continue; + case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue; + case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue; + case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; + case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; + case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; + case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; + case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; + case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; + case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; + case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; + default: + Error(ecINTERNAL_ERROR, 2); + continue; + } + } + + default: + Error(ecINTERNAL_ERROR, 3); + return 0; + } // switch CmdCode + } // for all bytecode tokens + + return Stack[m_nFinalResultIdx]; + } + + //--------------------------------------------------------------------------- + void ParserBase::CreateRPN() const + { + if (!m_pTokenReader->GetExpr().length()) + Error(ecUNEXPECTED_EOF, 0); + + ParserStack<token_type> stOpt, stVal; + ParserStack<int> stArgCount; + token_type opta, opt; // for storing operators + token_type val, tval; // for storing value + + ReInit(); + + // The outermost counter counts the number of separated items + // such as in "a=10,b=20,c=c+a" + stArgCount.push(1); + + for(;;) + { + opt = m_pTokenReader->ReadNextToken(); + + switch (opt.GetCode()) + { + // + // Next three are different kind of value entries + // + case cmSTRING: + opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token + stVal.push(opt); + m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer + break; + + case cmVAR: + stVal.push(opt); + m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) ); + break; + + case cmVAL: + stVal.push(opt); + m_vRPN.AddVal( opt.GetVal() ); + break; + + case cmELSE: + m_nIfElseCounter--; + if (m_nIfElseCounter<0) + Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + + ApplyRemainingOprt(stOpt, stVal); + m_vRPN.AddIfElse(cmELSE); + stOpt.push(opt); + break; + + + case cmARG_SEP: + if (stArgCount.empty()) + Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + + ++stArgCount.top(); + // fallthrough intentional (no break!) + + case cmEND: + ApplyRemainingOprt(stOpt, stVal); + break; + + case cmBC: + { + // The argument count for parameterless functions is zero + // by default an opening bracket sets parameter count to 1 + // in preparation of arguments to come. If the last token + // was an opening bracket we know better... + if (opta.GetCode()==cmBO) + --stArgCount.top(); + + ApplyRemainingOprt(stOpt, stVal); + + // Check if the bracket content has been evaluated completely + if (stOpt.size() && stOpt.top().GetCode()==cmBO) + { + // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check + // if there is either a function or a sign pending + // neither the opening nor the closing bracket will be pushed back to + // the operator stack + // Check if a function is standing in front of the opening bracket, + // if yes evaluate it afterwards check for infix operators + assert(stArgCount.size()); + int iArgCount = stArgCount.pop(); + + stOpt.pop(); // Take opening bracket from stack + + if (iArgCount>1 && ( stOpt.size()==0 || + (stOpt.top().GetCode()!=cmFUNC && + stOpt.top().GetCode()!=cmFUNC_BULK && + stOpt.top().GetCode()!=cmFUNC_STR) ) ) + Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); + + // The opening bracket was popped from the stack now check if there + // was a function before this bracket + if (stOpt.size() && + stOpt.top().GetCode()!=cmOPRT_INFIX && + stOpt.top().GetCode()!=cmOPRT_BIN && + stOpt.top().GetFuncAddr()!=0) + { + ApplyFunc(stOpt, stVal, iArgCount); + } + } + } // if bracket content is evaluated + break; + + // + // Next are the binary operator entries + // + //case cmAND: // built in binary operators + //case cmOR: + //case cmXOR: + case cmIF: + m_nIfElseCounter++; + // fallthrough intentional (no break!) + + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + case cmOPRT_BIN: + + // A binary operator (user defined or built in) has been found. + while ( stOpt.size() && + stOpt.top().GetCode() != cmBO && + stOpt.top().GetCode() != cmELSE && + stOpt.top().GetCode() != cmIF) + { + int nPrec1 = GetOprtPrecedence(stOpt.top()), + nPrec2 = GetOprtPrecedence(opt); + + if (stOpt.top().GetCode()==opt.GetCode()) + { + + // Deal with operator associativity + EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); + if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || + (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) ) + { + break; + } + } + else if (nPrec1 < nPrec2) + { + // In case the operators are not equal the precedence decides alone... + break; + } + + if (stOpt.top().GetCode()==cmOPRT_INFIX) + ApplyFunc(stOpt, stVal, 1); + else + ApplyBinOprt(stOpt, stVal); + } // while ( ... ) + + if (opt.GetCode()==cmIF) + m_vRPN.AddIfElse(opt.GetCode()); + + // The operator can't be evaluated right now, push back to the operator stack + stOpt.push(opt); + break; + + // + // Last section contains functions and operators implicitly mapped to functions + // + case cmBO: + stArgCount.push(1); + stOpt.push(opt); + break; + + case cmOPRT_INFIX: + case cmFUNC: + case cmFUNC_BULK: + case cmFUNC_STR: + stOpt.push(opt); + break; + + case cmOPRT_POSTFIX: + stOpt.push(opt); + ApplyFunc(stOpt, stVal, 1); // this is the postfix operator + break; + + default: Error(ecINTERNAL_ERROR, 3); + } // end of switch operator-token + + opta = opt; + + if ( opt.GetCode() == cmEND ) + { + m_vRPN.Finalize(); + break; + } + + if (ParserBase::g_DbgDumpStack) + { + StackDump(stVal, stOpt); + m_vRPN.AsciiDump(); + } + } // while (true) + + if (ParserBase::g_DbgDumpCmdCode) + m_vRPN.AsciiDump(); + + if (m_nIfElseCounter>0) + Error(ecMISSING_ELSE_CLAUSE); + + // get the last value (= final result) from the stack + MUP_ASSERT(stArgCount.size()==1); + m_nFinalResultIdx = stArgCount.top(); + if (m_nFinalResultIdx==0) + Error(ecINTERNAL_ERROR, 9); + + if (stVal.size()==0) + Error(ecEMPTY_EXPRESSION); + + if (stVal.top().GetType()!=tpDBL) + Error(ecSTR_RESULT); + + m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); + } + + //--------------------------------------------------------------------------- + /** \brief One of the two main parse functions. + \sa ParseCmdCode(...) + + Parse expression from input string. Perform syntax checking and create + bytecode. After parsing the string and creating the bytecode the function + pointer #m_pParseFormula will be changed to the second parse routine the + uses bytecode instead of string parsing. + */ + value_type ParserBase::ParseString() const + { + try + { + CreateRPN(); + m_pParseFormula = &ParserBase::ParseCmdCode; + return (this->*m_pParseFormula)(); + } + catch(ParserError &exc) + { + exc.SetFormula(m_pTokenReader->GetExpr()); + throw; + } + } + + //--------------------------------------------------------------------------- + /** \brief Create an error containing the parse error position. + + This function will create an Parser Exception object containing the error text and + its position. + + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws thats the only purpose of this function. + */ + void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const + { + throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined variables. + \throw nothrow + + Resets the parser to string parsing mode by calling #ReInit. + */ + void ParserBase::ClearVar() + { + m_VarDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Remove a variable from internal storage. + \throw nothrow + + Removes a variable if it exists. If the Variable does not exist nothing will be done. + */ + void ParserBase::RemoveVar(const string_type &a_strVarName) + { + varmap_type::iterator item = m_VarDef.find(a_strVarName); + if (item!=m_VarDef.end()) + { + m_VarDef.erase(item); + ReInit(); + } + } + + //------------------------------------------------------------------------------ + /** \brief Clear all functions. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearFun() + { + m_FunDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined constants. + + Both numeric and string constants will be removed from the internal storage. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearConst() + { + m_ConstDef.clear(); + m_StrVarDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined postfix operators. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearPostfixOprt() + { + m_PostOprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined binary operators. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearOprt() + { + m_OprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear the user defined Prefix operators. + \post Resets the parser to string parser mode. + \throw nothrow + */ + void ParserBase::ClearInfixOprt() + { + m_InfixOprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Enable or disable the formula optimization feature. + \post Resets the parser to string parser mode. + \throw nothrow + */ + void ParserBase::EnableOptimizer(bool a_bIsOn) + { + m_vRPN.EnableOptimizer(a_bIsOn); + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Enable the dumping of bytecode and stack content on the console. + \param bDumpCmd Flag to enable dumping of the current bytecode to the console. + \param bDumpStack Flag to enable dumping of the stack content is written to the console. + + This function is for debug purposes only! + */ + void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) + { + ParserBase::g_DbgDumpCmdCode = bDumpCmd; + ParserBase::g_DbgDumpStack = bDumpStack; + } + + //------------------------------------------------------------------------------ + /** \brief Enable or disable the built in binary operators. + \throw nothrow + \sa m_bBuiltInOp, ReInit() + + If you disable the built in binary operators there will be no binary operators + defined. Thus you must add them manually one by one. It is not possible to + disable built in operators selectively. This function will Reinitialize the + parser by calling ReInit(). + */ + void ParserBase::EnableBuiltInOprt(bool a_bIsOn) + { + m_bBuiltInOp = a_bIsOn; + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Query status of built in variables. + \return #m_bBuiltInOp; true if built in operators are enabled. + \throw nothrow + */ + bool ParserBase::HasBuiltInOprt() const + { + return m_bBuiltInOp; + } + + //------------------------------------------------------------------------------ + /** \brief Get the argument separator character. + */ + char_type ParserBase::GetArgSep() const + { + return m_pTokenReader->GetArgSep(); + } + + //------------------------------------------------------------------------------ + /** \brief Set argument separator. + \param cArgSep the argument separator character. + */ + void ParserBase::SetArgSep(char_type cArgSep) + { + m_pTokenReader->SetArgSep(cArgSep); + } + + //------------------------------------------------------------------------------ + /** \brief Dump stack content. + + This function is used for debugging only. + */ + void ParserBase::StackDump(const ParserStack<token_type> &a_stVal, + const ParserStack<token_type> &a_stOprt) const + { + ParserStack<token_type> stOprt(a_stOprt), + stVal(a_stVal); + + mu::console() << _T("\nValue stack:\n"); + while ( !stVal.empty() ) + { + token_type val = stVal.pop(); + if (val.GetType()==tpSTR) + mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); + else + mu::console() << _T(" ") << val.GetVal() << _T(" "); + } + mu::console() << "\nOperator stack:\n"; + + while ( !stOprt.empty() ) + { + if (stOprt.top().GetCode()<=cmASSIGN) + { + mu::console() << _T("OPRT_INTRNL \"") + << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] + << _T("\" \n"); + } + else + { + switch(stOprt.top().GetCode()) + { + case cmVAR: mu::console() << _T("VAR\n"); break; + case cmVAL: mu::console() << _T("VAL\n"); break; + case cmFUNC: mu::console() << _T("FUNC \"") + << stOprt.top().GetAsString() + << _T("\"\n"); break; + case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") + << stOprt.top().GetAsString() + << _T("\"\n"); break; + case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"") + << stOprt.top().GetAsString() + << _T("\"\n"); break; + case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") + << stOprt.top().GetAsString() + << _T("\"\n"); break; + case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break; + case cmEND: mu::console() << _T("END\n"); break; + case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break; + case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break; + case cmBC: mu::console() << _T("BRACKET \")\"\n"); break; + case cmIF: mu::console() << _T("IF\n"); break; + case cmELSE: mu::console() << _T("ELSE\n"); break; + case cmENDIF: mu::console() << _T("ENDIF\n"); break; + default: mu::console() << stOprt.top().GetCode() << _T(" "); break; + } + } + stOprt.pop(); + } + + mu::console() << dec << endl; + } + + //------------------------------------------------------------------------------ + /** \brief Evaluate an expression containing comma separated subexpressions + \param [out] nStackSize The total number of results available + \return Pointer to the array containing all expression results + + This member function can be used to retrieve all results of an expression + made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") + */ + value_type* ParserBase::Eval(int &nStackSize) const + { + (this->*m_pParseFormula)(); + nStackSize = m_nFinalResultIdx; + + // (for historic reasons the stack starts at position 1) + return &m_vStackBuffer[1]; + } + + //--------------------------------------------------------------------------- + /** \brief Return the number of results on the calculation stack. + + If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). + There may be more than one return value. This function returns the number of + available results. + */ + int ParserBase::GetNumResults() const + { + return m_nFinalResultIdx; + } + + //--------------------------------------------------------------------------- + /** \brief Calculate the result. + + A note on const correctness: + I consider it important that Calc is a const function. + Due to caching operations Calc changes only the state of internal variables with one exception + m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making + Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. + + \pre A formula must be set. + \pre Variables must have been set (if needed) + + \sa #m_pParseFormula + \return The evaluation result + \throw ParseException if no Formula is set or in case of any other error related to the formula. + */ + value_type ParserBase::Eval() const + { + return (this->*m_pParseFormula)(); + } + + //--------------------------------------------------------------------------- + void ParserBase::Eval(value_type *results, int nBulkSize) + { +/* <ibg 2014-09-24/> Commented because it is making a unit test impossible + + // Parallelization does not make sense for fewer than 10000 computations + // due to thread creation overhead. If the bulk size is below 2000 + // computation is refused. + if (nBulkSize<2000) + { + throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); + } +*/ + CreateRPN(); + + int i = 0; + +#ifdef MUP_USE_OPENMP +//#define DEBUG_OMP_STUFF + #ifdef DEBUG_OMP_STUFF + int *pThread = new int[nBulkSize]; + int *pIdx = new int[nBulkSize]; + #endif + + int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads); + int nThreadID = 0, ct = 0; + omp_set_num_threads(nMaxThreads); + + #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID) + for (i=0; i<nBulkSize; ++i) + { + nThreadID = omp_get_thread_num(); + results[i] = ParseCmdCodeBulk(i, nThreadID); + + #ifdef DEBUG_OMP_STUFF + #pragma omp critical + { + pThread[ct] = nThreadID; + pIdx[ct] = i; + ct++; + } + #endif + } + +#ifdef DEBUG_OMP_STUFF + FILE *pFile = fopen("bulk_dbg.txt", "w"); + for (i=0; i<nBulkSize; ++i) + { + fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]); + } + + delete [] pIdx; + delete [] pThread; + + fclose(pFile); +#endif + +#else + for (i=0; i<nBulkSize; ++i) + { + results[i] = ParseCmdCodeBulk(i, 0); + } +#endif + + } +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserBytecode.cpp b/ThirdParty/MuParser/src/muParserBytecode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38ae3f933422c779b66807493c8fdd61b2399e95 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserBytecode.cpp @@ -0,0 +1,588 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "muParserBytecode.h" + +#include <algorithm> +#include <cassert> +#include <string> +#include <stack> +#include <vector> +#include <iostream> + +#include "muParserDef.h" +#include "muParserError.h" +#include "muParserToken.h" +#include "muParserStack.h" +#include "muParserTemplateMagic.h" + + +namespace mu +{ + //--------------------------------------------------------------------------- + /** \brief Bytecode default constructor. */ + ParserByteCode::ParserByteCode() + :m_iStackPos(0) + ,m_iMaxStackSize(0) + ,m_vRPN() + ,m_bEnableOptimizer(true) + { + m_vRPN.reserve(50); + } + + //--------------------------------------------------------------------------- + /** \brief Copy constructor. + + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) + */ + ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) + { + Assign(a_ByteCode); + } + + //--------------------------------------------------------------------------- + /** \brief Assignment operator. + + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) + */ + ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode) + { + Assign(a_ByteCode); + return *this; + } + + //--------------------------------------------------------------------------- + void ParserByteCode::EnableOptimizer(bool bStat) + { + m_bEnableOptimizer = bStat; + } + + //--------------------------------------------------------------------------- + /** \brief Copy state of another object to this. + + \throw nowthrow + */ + void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) + { + if (this==&a_ByteCode) + return; + + m_iStackPos = a_ByteCode.m_iStackPos; + m_vRPN = a_ByteCode.m_vRPN; + m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; + m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; + } + + //--------------------------------------------------------------------------- + /** \brief Add a Variable pointer to bytecode. + \param a_pVar Pointer to be added. + \throw nothrow + */ + void ParserByteCode::AddVar(value_type *a_pVar) + { + ++m_iStackPos; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + // optimization does not apply + SToken tok; + tok.Cmd = cmVAR; + tok.Val.ptr = a_pVar; + tok.Val.data = 1; + tok.Val.data2 = 0; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + /** \brief Add a Variable pointer to bytecode. + + Value entries in byte code consist of: + <ul> + <li>value array position of the value</li> + <li>the operator code according to ParserToken::cmVAL</li> + <li>the value stored in #mc_iSizeVal number of bytecode entries.</li> + </ul> + + \param a_pVal Value to be added. + \throw nothrow + */ + void ParserByteCode::AddVal(value_type a_fVal) + { + ++m_iStackPos; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + // If optimization does not apply + SToken tok; + tok.Cmd = cmVAL; + tok.Val.ptr = NULL; + tok.Val.data = 0; + tok.Val.data2 = a_fVal; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) + { + std::size_t sz = m_vRPN.size(); + value_type &x = m_vRPN[sz-2].Val.data2, + &y = m_vRPN[sz-1].Val.data2; + switch (a_Oprt) + { + case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; + case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; + case cmLT: x = x < y; m_vRPN.pop_back(); break; + case cmGT: x = x > y; m_vRPN.pop_back(); break; + case cmLE: x = x <= y; m_vRPN.pop_back(); break; + case cmGE: x = x >= y; m_vRPN.pop_back(); break; + case cmNEQ: x = x != y; m_vRPN.pop_back(); break; + case cmEQ: x = x == y; m_vRPN.pop_back(); break; + case cmADD: x = x + y; m_vRPN.pop_back(); break; + case cmSUB: x = x - y; m_vRPN.pop_back(); break; + case cmMUL: x = x * y; m_vRPN.pop_back(); break; + case cmDIV: + +#if defined(MUP_MATH_EXCEPTIONS) + if (y==0) + throw ParserError(ecDIV_BY_ZERO, _T("0")); +#endif + + x = x / y; + m_vRPN.pop_back(); + break; + + case cmPOW: x = MathImpl<value_type>::Pow(x, y); + m_vRPN.pop_back(); + break; + + default: + break; + } // switch opcode + } + + //--------------------------------------------------------------------------- + /** \brief Add an operator identifier to bytecode. + + Operator entries in byte code consist of: + <ul> + <li>value array position of the result</li> + <li>the operator code according to ParserToken::ECmdCode</li> + </ul> + + \sa ParserToken::ECmdCode + */ + void ParserByteCode::AddOp(ECmdCode a_Oprt) + { + bool bOptimized = false; + + if (m_bEnableOptimizer) + { + std::size_t sz = m_vRPN.size(); + + // Check for foldable constants like: + // cmVAL cmVAL cmADD + // where cmADD can stand fopr any binary operator applied to + // two constant values. + if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL) + { + ConstantFolding(a_Oprt); + bOptimized = true; + } + else + { + switch(a_Oprt) + { + case cmPOW: + // Optimization for polynomials of low order + if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL) + { + if (m_vRPN[sz-1].Val.data2==2) + m_vRPN[sz-2].Cmd = cmVARPOW2; + else if (m_vRPN[sz-1].Val.data2==3) + m_vRPN[sz-2].Cmd = cmVARPOW3; + else if (m_vRPN[sz-1].Val.data2==4) + m_vRPN[sz-2].Cmd = cmVARPOW4; + else + break; + + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmSUB: + case cmADD: + // Simple optimization based on pattern recognition for a shitload of different + // bytecode combinations of addition/subtraction + if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || + (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || + (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || + (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) || + (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || + (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || + (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || + (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ) + { + assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) || + (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || + (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ); + + m_vRPN[sz-2].Cmd = cmVARMUL; + m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable + m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset + m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmMUL: + if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || + (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) + { + m_vRPN[sz-2].Cmd = cmVARMUL; + m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); + m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2; + m_vRPN[sz-2].Val.data2 = 0; + m_vRPN.pop_back(); + bOptimized = true; + } + else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || + (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ) + { + // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 + m_vRPN[sz-2].Cmd = cmVARMUL; + m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); + if (m_vRPN[sz-1].Cmd == cmVAL) + { + m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2; + m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2; + } + else + { + m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2; + m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2; + } + m_vRPN.pop_back(); + bOptimized = true; + } + else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && + m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr) + { + // Optimization: a*a -> a^2 + m_vRPN[sz-2].Cmd = cmVARPOW2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmDIV: + if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0) + { + // Optimization: 4*a/2 -> 2*a + m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2; + m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + } // switch a_Oprt + } + } + + // If optimization can't be applied just write the value + if (!bOptimized) + { + --m_iStackPos; + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); + } + } + + //--------------------------------------------------------------------------- + void ParserByteCode::AddIfElse(ECmdCode a_Oprt) + { + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + /** \brief Add an assignment operator + + Operator entries in byte code consist of: + <ul> + <li>cmASSIGN code</li> + <li>the pointer of the destination variable</li> + </ul> + + \sa ParserToken::ECmdCode + */ + void ParserByteCode::AddAssignOp(value_type *a_pVar) + { + --m_iStackPos; + + SToken tok; + tok.Cmd = cmASSIGN; + tok.Oprt.ptr = a_pVar; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + /** \brief Add function to bytecode. + + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. + */ + void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) + { + if (a_iArgc>=0) + { + m_iStackPos = m_iStackPos - a_iArgc + 1; + } + else + { + // function with unlimited number of arguments + m_iStackPos = m_iStackPos + a_iArgc + 1; + } + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + SToken tok; + tok.Cmd = cmFUNC; + tok.Fun.argc = a_iArgc; + tok.Fun.ptr = a_pFun; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + /** \brief Add a bulk function to bytecode. + + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. + */ + void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) + { + m_iStackPos = m_iStackPos - a_iArgc + 1; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + SToken tok; + tok.Cmd = cmFUNC_BULK; + tok.Fun.argc = a_iArgc; + tok.Fun.ptr = a_pFun; + m_vRPN.push_back(tok); + } + + //--------------------------------------------------------------------------- + /** \brief Add Strung function entry to the parser bytecode. + \throw nothrow + + A string function entry consists of the stack position of the return value, + followed by a cmSTRFUNC code, the function pointer and an index into the + string buffer maintained by the parser. + */ + void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) + { + m_iStackPos = m_iStackPos - a_iArgc + 1; + + SToken tok; + tok.Cmd = cmFUNC_STR; + tok.Fun.argc = a_iArgc; + tok.Fun.idx = a_iIdx; + tok.Fun.ptr = a_pFun; + m_vRPN.push_back(tok); + + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + } + + //--------------------------------------------------------------------------- + /** \brief Add end marker to bytecode. + + \throw nothrow + */ + void ParserByteCode::Finalize() + { + SToken tok; + tok.Cmd = cmEND; + m_vRPN.push_back(tok); + rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit + + // Determine the if-then-else jump offsets + ParserStack<int> stIf, stElse; + int idx; + for (int i=0; i<(int)m_vRPN.size(); ++i) + { + switch(m_vRPN[i].Cmd) + { + case cmIF: + stIf.push(i); + break; + + case cmELSE: + stElse.push(i); + idx = stIf.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; + + case cmENDIF: + idx = stElse.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; + + default: + break; + } + } + } + + //--------------------------------------------------------------------------- + const SToken* ParserByteCode::GetBase() const + { + if (m_vRPN.size()==0) + throw ParserError(ecINTERNAL_ERROR); + else + return &m_vRPN[0]; + } + + //--------------------------------------------------------------------------- + std::size_t ParserByteCode::GetMaxStackSize() const + { + return m_iMaxStackSize+1; + } + + //--------------------------------------------------------------------------- + /** \brief Returns the number of entries in the bytecode. */ + std::size_t ParserByteCode::GetSize() const + { + return m_vRPN.size(); + } + + //--------------------------------------------------------------------------- + /** \brief Delete the bytecode. + + \throw nothrow + + The name of this function is a violation of my own coding guidelines + but this way it's more in line with the STL functions thus more + intuitive. + */ + void ParserByteCode::clear() + { + m_vRPN.clear(); + m_iStackPos = 0; + m_iMaxStackSize = 0; + } + + //--------------------------------------------------------------------------- + /** \brief Dump bytecode (for debugging only!). */ + void ParserByteCode::AsciiDump() + { + if (!m_vRPN.size()) + { + mu::console() << _T("No bytecode available\n"); + return; + } + + mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n"); + for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i) + { + mu::console() << std::dec << i << _T(" : \t"); + switch (m_vRPN[i].Cmd) + { + case cmVAL: mu::console() << _T("VAL \t"); + mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n"); + break; + + case cmVAR: mu::console() << _T("VAR \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW2: mu::console() << _T("VARPOW2 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW3: mu::console() << _T("VARPOW3 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW4: mu::console() << _T("VARPOW4 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARMUL: mu::console() << _T("VARMUL \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]"); + mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]"); + mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n"); + break; + + case cmFUNC: mu::console() << _T("CALL\t"); + mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Fun.ptr << _T("]"); + mu::console() << _T("\n"); + break; + + case cmFUNC_STR: + mu::console() << _T("CALL STRFUNC\t"); + mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); + mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("]"); + mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Fun.ptr << _T("]\n"); + break; + + case cmLT: mu::console() << _T("LT\n"); break; + case cmGT: mu::console() << _T("GT\n"); break; + case cmLE: mu::console() << _T("LE\n"); break; + case cmGE: mu::console() << _T("GE\n"); break; + case cmEQ: mu::console() << _T("EQ\n"); break; + case cmNEQ: mu::console() << _T("NEQ\n"); break; + case cmADD: mu::console() << _T("ADD\n"); break; + case cmLAND: mu::console() << _T("&&\n"); break; + case cmLOR: mu::console() << _T("||\n"); break; + case cmSUB: mu::console() << _T("SUB\n"); break; + case cmMUL: mu::console() << _T("MUL\n"); break; + case cmDIV: mu::console() << _T("DIV\n"); break; + case cmPOW: mu::console() << _T("POW\n"); break; + + case cmIF: mu::console() << _T("IF\t"); + mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n"); + break; + + case cmELSE: mu::console() << _T("ELSE\t"); + mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n"); + break; + + case cmENDIF: mu::console() << _T("ENDIF\n"); break; + + case cmASSIGN: + mu::console() << _T("ASSIGN\t"); + mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n"); + break; + + default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); + break; + } // switch cmdCode + } // while bytecode + + mu::console() << _T("END") << std::endl; + } +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserCallback.cpp b/ThirdParty/MuParser/src/muParserCallback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6aec1ae037823ae519cbe10469162b0b86d0cd9 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserCallback.cpp @@ -0,0 +1,463 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "muParserCallback.h" + +/** \file + \brief Implementation of the parser callback class. +*/ + + +namespace mu +{ + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(0) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) + :m_pFun((void*)a_pFun) + ,m_iArgc(1) + ,m_iPri(a_iPrec) + ,m_eOprtAsct(oaNONE) + ,m_iCode(a_iCode) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + /** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow + */ + ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(2) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + /** \brief Constructor for constructing binary operator callbacks. + \param a_pFun Pointer to a static function taking two arguments + \param a_bAllowOpti A flag indicating this function can be optimized + \param a_iPrec The operator precedence + \param a_eOprtAsct The operators associativity + \throw nothrow + */ + ParserCallback::ParserCallback(fun_type2 a_pFun, + bool a_bAllowOpti, + int a_iPrec, + EOprtAssociativity a_eOprtAsct) + :m_pFun((void*)a_pFun) + ,m_iArgc(2) + ,m_iPri(a_iPrec) + ,m_eOprtAsct(a_eOprtAsct) + ,m_iCode(cmOPRT_BIN) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(3) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(4) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(5) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(6) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(7) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(8) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(9) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(10) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(0) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(1) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + /** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow + */ + ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(2) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(3) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(4) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(5) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(6) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(7) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(8) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(9) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(10) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_BULK) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(-1) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC) + ,m_iType(tpDBL) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(0) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_STR) + ,m_iType(tpSTR) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(1) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_STR) + ,m_iType(tpSTR) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + ,m_iArgc(2) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmFUNC_STR) + ,m_iType(tpSTR) + ,m_bAllowOpti(a_bAllowOpti) + {} + + + //--------------------------------------------------------------------------- + /** \brief Default constructor. + \throw nothrow + */ + ParserCallback::ParserCallback() + :m_pFun(0) + ,m_iArgc(0) + ,m_iPri(-1) + ,m_eOprtAsct(oaNONE) + ,m_iCode(cmUNKNOWN) + ,m_iType(tpVOID) + ,m_bAllowOpti(0) + {} + + + //--------------------------------------------------------------------------- + /** \brief Copy constructor. + \throw nothrow + */ + ParserCallback::ParserCallback(const ParserCallback &ref) + { + m_pFun = ref.m_pFun; + m_iArgc = ref.m_iArgc; + m_bAllowOpti = ref.m_bAllowOpti; + m_iCode = ref.m_iCode; + m_iType = ref.m_iType; + m_iPri = ref.m_iPri; + m_eOprtAsct = ref.m_eOprtAsct; + } + + //--------------------------------------------------------------------------- + /** \brief Clone this instance and return a pointer to the new instance. */ + ParserCallback* ParserCallback::Clone() const + { + return new ParserCallback(*this); + } + + //--------------------------------------------------------------------------- + /** \brief Return tru if the function is conservative. + + Conservative functions return always the same result for the same argument. + \throw nothrow + */ + bool ParserCallback::IsOptimizable() const + { + return m_bAllowOpti; + } + + //--------------------------------------------------------------------------- + /** \brief Get the callback address for the parser function. + + The type of the address is void. It needs to be recasted according to the + argument number to the right type. + + \throw nothrow + \return #pFun + */ + void* ParserCallback::GetAddr() const + { + return m_pFun; + } + + //--------------------------------------------------------------------------- + /** \brief Return the callback code. */ + ECmdCode ParserCallback::GetCode() const + { + return m_iCode; + } + + //--------------------------------------------------------------------------- + ETypeCode ParserCallback::GetType() const + { + return m_iType; + } + + + //--------------------------------------------------------------------------- + /** \brief Return the operator precedence. + \throw nothrown + + Only valid if the callback token is an operator token (binary or infix). + */ + int ParserCallback::GetPri() const + { + return m_iPri; + } + + //--------------------------------------------------------------------------- + /** \brief Return the operators associativity. + \throw nothrown + + Only valid if the callback token is a binary operator token. + */ + EOprtAssociativity ParserCallback::GetAssociativity() const + { + return m_eOprtAsct; + } + + //--------------------------------------------------------------------------- + /** \brief Returns the number of function Arguments. */ + int ParserCallback::GetArgc() const + { + return m_iArgc; + } +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserDLL.cpp b/ThirdParty/MuParser/src/muParserDLL.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a05476655614bdf5ac9388a8dd237b49e9ac3694 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserDLL.cpp @@ -0,0 +1,1096 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2004-2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#if defined(MUPARSER_DLL) + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +#include "muParserDLL.h" +#include "muParser.h" +#include "muParserInt.h" +#include "muParserError.h" + + +#define MU_TRY \ + try \ + { + +#define MU_CATCH \ + } \ + catch (muError_t &e) \ + { \ + ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \ + pTag->exc = e; \ + pTag->bError = true; \ +if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } \ + catch (...) \ + { \ + ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \ + pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ + pTag->bError = true; \ +if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } + +/** \file + \brief This file contains the implementation of the DLL interface of muparser. + */ + +//--------------------------------------------------------------------------- +// private types +typedef mu::ParserBase::exception_type muError_t; +typedef mu::ParserBase muParser_t; + +int g_nBulkSize; + +//--------------------------------------------------------------------------- +class ParserTag +{ +public: + ParserTag(int nType) + :pParser((nType == muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() : + (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL) + , exc() + , errHandler(NULL) + , bError(false) + , m_nParserType(nType) + {} + + ~ParserTag() + { + delete pParser; + } + + mu::ParserBase *pParser; + mu::ParserBase::exception_type exc; + muErrorHandler_t errHandler; + bool bError; + +private: + ParserTag(const ParserTag &ref); + ParserTag& operator=(const ParserTag &ref); + + int m_nParserType; +}; + +static muChar_t s_tmpOutBuf[2048]; + +//--------------------------------------------------------------------------- +// +// +// unexported functions +// +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +muParser_t* AsParser(muParserHandle_t a_hParser) +{ + return static_cast<ParserTag*>(a_hParser)->pParser; +} + +//--------------------------------------------------------------------------- +ParserTag* AsParserTag(muParserHandle_t a_hParser) +{ + return static_cast<ParserTag*>(a_hParser); +} + +//--------------------------------------------------------------------------- +#if defined(_WIN32) +#define _CRT_SECURE_NO_DEPRECATE + +BOOL APIENTRY DllMain(HANDLE /*hModule*/, + DWORD ul_reason_for_call, + LPVOID /*lpReserved*/) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +#endif + +//--------------------------------------------------------------------------- +// +// +// exported functions +// +// +//--------------------------------------------------------------------------- + +API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->SetVarFactory(a_pFactory, pUserData); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Create a new Parser instance and return its handle. +*/ +API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) +{ + switch (nBaseType) + { + case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); + case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); + default: return NULL; + } +} + +//--------------------------------------------------------------------------- +/** \brief Release the parser instance related with a parser handle. +*/ +API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) +{ + MU_TRY + ParserTag* p = static_cast<ParserTag*>(a_hParser); + delete p; + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + +#ifndef _UNICODE + sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str()); +#else + wsprintf(s_tmpOutBuf, _T("%s"), p->GetVersion().c_str()); +#endif + + return s_tmpOutBuf; + MU_CATCH + + return _T(""); +} + +//--------------------------------------------------------------------------- +/** \brief Evaluate the expression. +*/ +API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(); + MU_CATCH + + return 0; +} + +//--------------------------------------------------------------------------- +API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum) +{ + MU_TRY + assert(nNum != NULL); + + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(*nNum); + MU_CATCH + + return 0; +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->Eval(a_res, nSize); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetExpr(a_szExpr); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->RemoveVar(a_szName); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. + */ +API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearVar(); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. + */ +API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearConst(); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Clear all user defined operators. + \param a_hParser Handle to the parser instance. + */ +API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearOprt(); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearFun(); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun0_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun2_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun3_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun4_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun5_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun6_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun7_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun8_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun9_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFun10_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muBulkFun0_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muBulkFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muBulkFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun4_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun5_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun6_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun7_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun8_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun9_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muBulkFun10_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muStrFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muStrFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muStrFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muMultFun_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun2_t a_pFun, + muInt_t a_nPrec, + muInt_t a_nOprtAsct, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprt(a_szName, + a_pFun, + a_nPrec, + (mu::EOprtAssociativity)a_nOprtAsct, + a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFloat_t *a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFloat_t *a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, + const muChar_t *a_szName, + muFloat_t a_fVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineConst(a_szName, a_fVal); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, + const muChar_t *a_szName, + const muChar_t *a_szVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineStrConst(a_szName, a_szVal); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str()); +#else + wsprintf(s_tmpOutBuf, _T("%s"), p->GetExpr().c_str()); +#endif + + return s_tmpOutBuf; + + MU_CATCH + + return _T(""); +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + MU_CATCH +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + MU_CATCH +} + +// Define character sets for identifiers +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, + const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineNameChars(a_szCharset); +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, + const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprtChars(a_szCharset); +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, + const muChar_t *a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprtChars(a_szCharset); +} + +//--------------------------------------------------------------------------- +/** \brief Get the number of variables defined in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar + */ +API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + +//--------------------------------------------------------------------------- +/** \brief Return a variable that is used in an expression. + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. + */ +API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, + unsigned a_iVar, + const muChar_t **a_szName, + muFloat_t **a_pVar) +{ + // A static buffer is needed for the name since i cant return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), sizeof(szName)); +#else + wcsncpy(szName, item->first.c_str(), sizeof(szName)); +#endif + + szName[sizeof(szName)-1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + + MU_CATCH + + *a_szName = 0; + *a_pVar = 0; +} + +//--------------------------------------------------------------------------- +/** \brief Get the number of variables used in the expression currently set in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar + */ +API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + +//--------------------------------------------------------------------------- +/** \brief Return a variable that is used in an expression. + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. + + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow + */ +API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, + unsigned a_iVar, + const muChar_t **a_szName, + muFloat_t **a_pVar) +{ + // A static buffer is needed for the name since i cant return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), sizeof(szName)); +#else + wcsncpy(szName, item->first.c_str(), sizeof(szName)); +#endif + + szName[sizeof(szName)-1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + + MU_CATCH + + *a_szName = 0; + *a_pVar = 0; +} + +//--------------------------------------------------------------------------- +/** \brief Return the number of constants defined in a parser. */ +API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + return (int)ValMap.size(); + MU_CATCH + + return 0; // never reached +} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetArgSep(cArgSep); + MU_CATCH +} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ResetLocale(); + MU_CATCH +} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetDecSep(cDecSep); + MU_CATCH +} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetThousandsSep(cThousandsSep); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Retrieve name and value of a single parser constant. + \param a_hParser [in] a valid parser handle + \param a_iVar [in] Index of the constant to query + \param a_pszName [out] pointer to a null terminated string with the constant name + \param [out] The constant value + */ +API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, + unsigned a_iVar, + const muChar_t **a_pszName, + muFloat_t *a_fVal) +{ + // A static buffer is needed for the name since i cant return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + + if (a_iVar >= ValMap.size()) + { + *a_pszName = 0; + *a_fVal = 0; + return; + } + + mu::valmap_type::const_iterator item; + item = ValMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), sizeof(szName)); +#else + wcsncpy(szName, item->first.c_str(), sizeof(szName)); +#endif + + szName[sizeof(szName)-1] = 0; + + *a_pszName = &szName[0]; + *a_fVal = item->second; + return; + + MU_CATCH + + *a_pszName = 0; + *a_fVal = 0; +} + +//--------------------------------------------------------------------------- +/** \brief Add a custom value recognition function. +*/ +API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, + muIdentFun_t a_pFun) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->AddValIdent(a_pFun); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Query if an error occurred. + + After querying the internal error bit will be reset. So a consecutive call + will return false. + */ +API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) +{ + bool bError(AsParserTag(a_hParser)->bError); + AsParserTag(a_hParser)->bError = false; + return bError; +} + +//--------------------------------------------------------------------------- +/** \brief Reset the internal error flag. +*/ +API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) +{ + AsParserTag(a_hParser)->bError = false; +} + +//--------------------------------------------------------------------------- +API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) +{ + AsParserTag(a_hParser)->errHandler = a_pHandler; +} + +//--------------------------------------------------------------------------- +/** \brief Return the message associated with the last error. +*/ +API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t *pMsg = p->exc.GetMsg().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + sprintf(s_tmpOutBuf, "%s", pMsg); +#else + wsprintf(s_tmpOutBuf, _T("%s"), pMsg); +#endif + + return s_tmpOutBuf; +} + +//--------------------------------------------------------------------------- +/** \brief Return the message associated with the last error. +*/ +API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t *pToken = p->exc.GetToken().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + sprintf(s_tmpOutBuf, "%s", pToken); +#else + wsprintf(s_tmpOutBuf, _T("%s"), pToken); +#endif + + return s_tmpOutBuf; +} + +//--------------------------------------------------------------------------- +/** \brief Return the code associated with the last error. +*/ +API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) +{ + return AsParserTag(a_hParser)->exc.GetCode(); +} + +//--------------------------------------------------------------------------- +/** \brief Return the position associated with the last error. */ +API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) +{ + return (int)AsParserTag(a_hParser)->exc.GetPos(); +} + +////----------------------------------------------------------------------------------------------------- +//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser) +//{ +// return AsParserTag(a_hParser)->exc.GetExpr().c_str(); +//} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(muFloat_t*) mupCreateVar() +{ + return new muFloat_t(0); +} + +//----------------------------------------------------------------------------------------------------- +API_EXPORT(void) mupReleaseVar(muFloat_t *ptr) +{ + delete ptr; +} + +#endif // MUPARSER_DLL diff --git a/ThirdParty/MuParser/src/muParserError.cpp b/ThirdParty/MuParser/src/muParserError.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30c46484650ea12b1f47e2069d667722fc0f3523 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserError.cpp @@ -0,0 +1,337 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "muParserError.h" + + +namespace mu +{ + const ParserErrorMsg ParserErrorMsg::m_Instance; + + //------------------------------------------------------------------------------ + const ParserErrorMsg& ParserErrorMsg::Instance() + { + return m_Instance; + } + + //------------------------------------------------------------------------------ + string_type ParserErrorMsg::operator[](unsigned a_iIdx) const + { + return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type(); + } + + //--------------------------------------------------------------------------- + ParserErrorMsg::~ParserErrorMsg() + {} + + //--------------------------------------------------------------------------- + /** \brief Assignement operator is deactivated. + */ + ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& ) + { + assert(false); + return *this; + } + + //--------------------------------------------------------------------------- + ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&) + {} + + //--------------------------------------------------------------------------- + ParserErrorMsg::ParserErrorMsg() + :m_vErrMsg(0) + { + m_vErrMsg.resize(ecCOUNT); + + m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$."); + m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error"); + m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\"."); + m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\"."); + m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\"."); + m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\"."); + m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function."); + m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty."); + m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable."); + m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$"); + m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$"); + m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$"); + m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$"); + m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$"); + m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$"); + m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$"); + m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)"); + m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis"); + m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$"); + m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$"); + m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero"); + m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error"); + m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict"); + m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero)."); + m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator."); + m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$."); + m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$."); + m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument."); + m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected."); + m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$."); + m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string."); + m_vErrMsg[ecGENERIC] = _T("Parser error."); + m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator."); + m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket."); + m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause"); + m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$"); + m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)"); + + #if defined(_DEBUG) + for (int i=0; i<ecCOUNT; ++i) + if (!m_vErrMsg[i].length()) + assert(false); + #endif + } + + //--------------------------------------------------------------------------- + // + // ParserError class + // + //--------------------------------------------------------------------------- + + /** \brief Default constructor. */ + ParserError::ParserError() + :m_strMsg() + ,m_strFormula() + ,m_strTok() + ,m_iPos(-1) + ,m_iErrc(ecUNDEFINED) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + } + + //------------------------------------------------------------------------------ + /** \brief This Constructor is used for internal exceptions only. + + It does not contain any information but the error code. + */ + ParserError::ParserError(EErrorCodes a_iErrc) + :m_strMsg() + ,m_strFormula() + ,m_strTok() + ,m_iPos(-1) + ,m_iErrc(a_iErrc) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + m_strMsg = m_ErrMsg[m_iErrc]; + stringstream_type stream; + stream << (int)m_iPos; + ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); + ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok); + } + + //------------------------------------------------------------------------------ + /** \brief Construct an error from a message text. */ + ParserError::ParserError(const string_type &sMsg) + :m_ErrMsg(ParserErrorMsg::Instance()) + { + Reset(); + m_strMsg = sMsg; + } + + //------------------------------------------------------------------------------ + /** \brief Construct an error object. + \param [in] a_iErrc the error code. + \param [in] sTok The token string related to this error. + \param [in] sExpr The expression related to the error. + \param [in] a_iPos the position in the expression where the error occurred. + */ + ParserError::ParserError( EErrorCodes iErrc, + const string_type &sTok, + const string_type &sExpr, + int iPos ) + :m_strMsg() + ,m_strFormula(sExpr) + ,m_strTok(sTok) + ,m_iPos(iPos) + ,m_iErrc(iErrc) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + m_strMsg = m_ErrMsg[m_iErrc]; + stringstream_type stream; + stream << (int)m_iPos; + ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); + ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok); + } + + //------------------------------------------------------------------------------ + /** \brief Construct an error object. + \param [in] iErrc the error code. + \param [in] iPos the position in the expression where the error occurred. + \param [in] sTok The token string related to this error. + */ + ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) + :m_strMsg() + ,m_strFormula() + ,m_strTok(sTok) + ,m_iPos(iPos) + ,m_iErrc(iErrc) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + m_strMsg = m_ErrMsg[m_iErrc]; + stringstream_type stream; + stream << (int)m_iPos; + ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); + ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok); + } + + //------------------------------------------------------------------------------ + /** \brief Construct an error object. + \param [in] szMsg The error message text. + \param [in] iPos the position related to the error. + \param [in] sTok The token string related to this error. + */ + ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) + :m_strMsg(szMsg) + ,m_strFormula() + ,m_strTok(sTok) + ,m_iPos(iPos) + ,m_iErrc(ecGENERIC) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + stringstream_type stream; + stream << (int)m_iPos; + ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); + ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok); + } + + //------------------------------------------------------------------------------ + /** \brief Copy constructor. */ + ParserError::ParserError(const ParserError &a_Obj) + :m_strMsg(a_Obj.m_strMsg) + ,m_strFormula(a_Obj.m_strFormula) + ,m_strTok(a_Obj.m_strTok) + ,m_iPos(a_Obj.m_iPos) + ,m_iErrc(a_Obj.m_iErrc) + ,m_ErrMsg(ParserErrorMsg::Instance()) + { + } + + //------------------------------------------------------------------------------ + /** \brief Assignment operator. */ + ParserError& ParserError::operator=(const ParserError &a_Obj) + { + if (this==&a_Obj) + return *this; + + m_strMsg = a_Obj.m_strMsg; + m_strFormula = a_Obj.m_strFormula; + m_strTok = a_Obj.m_strTok; + m_iPos = a_Obj.m_iPos; + m_iErrc = a_Obj.m_iErrc; + return *this; + } + + //------------------------------------------------------------------------------ + ParserError::~ParserError() + {} + + //------------------------------------------------------------------------------ + /** \brief Replace all occurrences of a substring with another string. + \param strFind The string that shall be replaced. + \param strReplaceWith The string that should be inserted instead of strFind + */ + void ParserError::ReplaceSubString( string_type &strSource, + const string_type &strFind, + const string_type &strReplaceWith) + { + string_type strResult; + string_type::size_type iPos(0), iNext(0); + + for(;;) + { + iNext = strSource.find(strFind, iPos); + strResult.append(strSource, iPos, iNext-iPos); + + if( iNext==string_type::npos ) + break; + + strResult.append(strReplaceWith); + iPos = iNext + strFind.length(); + } + + strSource.swap(strResult); + } + + //------------------------------------------------------------------------------ + /** \brief Reset the erro object. */ + void ParserError::Reset() + { + m_strMsg = _T(""); + m_strFormula = _T(""); + m_strTok = _T(""); + m_iPos = -1; + m_iErrc = ecUNDEFINED; + } + + //------------------------------------------------------------------------------ + /** \brief Set the expression related to this error. */ + void ParserError::SetFormula(const string_type &a_strFormula) + { + m_strFormula = a_strFormula; + } + + //------------------------------------------------------------------------------ + /** \brief gets the expression related tp this error.*/ + const string_type& ParserError::GetExpr() const + { + return m_strFormula; + } + + //------------------------------------------------------------------------------ + /** \brief Returns the message string for this error. */ + const string_type& ParserError::GetMsg() const + { + return m_strMsg; + } + + //------------------------------------------------------------------------------ + /** \brief Return the formula position related to the error. + + If the error is not related to a distinct position this will return -1 + */ + int ParserError::GetPos() const + { + return m_iPos; + } + + //------------------------------------------------------------------------------ + /** \brief Return string related with this token (if available). */ + const string_type& ParserError::GetToken() const + { + return m_strTok; + } + + //------------------------------------------------------------------------------ + /** \brief Return the error code. */ + EErrorCodes ParserError::GetCode() const + { + return m_iErrc; + } +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserInt.cpp b/ThirdParty/MuParser/src/muParserInt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64a29ad9414071e580d49bb63c604bc2bd223cc8 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserInt.cpp @@ -0,0 +1,280 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2011 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "muParserInt.h" + +#include <cmath> +#include <algorithm> +#include <numeric> + +using namespace std; + +/** \file + \brief Implementation of a parser using integer value. +*/ + +/** \brief Namespace for mathematical applications. */ +namespace mu +{ +value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } +value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; } +value_type ParserInt::Ite(value_type v1, + value_type v2, + value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); } +value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } +value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } +value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } +value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } +value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } +value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } +value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } +value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } +value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } +value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } +value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } +value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } +value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } +value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } +value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } +value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } +value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } +value_type ParserInt::Not(value_type v) { return !Round(v); } + +value_type ParserInt::Pow(value_type v1, value_type v2) +{ + return std::pow((double)Round(v1), (double)Round(v2)); +} + +//--------------------------------------------------------------------------- +// Unary operator Callbacks: Infix operators +value_type ParserInt::UnaryMinus(value_type v) +{ + return -Round(v); +} + +//--------------------------------------------------------------------------- +value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc) +{ + if (!a_iArgc) + throw ParserError(_T("too few arguments for function sum.")); + + value_type fRes=0; + for (int i=0; i<a_iArgc; ++i) + fRes += a_afArg[i]; + + return fRes; +} + +//--------------------------------------------------------------------------- +value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc) +{ + if (!a_iArgc) + throw ParserError( _T("too few arguments for function min.") ); + + value_type fRes=a_afArg[0]; + for (int i=0; i<a_iArgc; ++i) + fRes = std::min(fRes, a_afArg[i]); + + return fRes; +} + +//--------------------------------------------------------------------------- +value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc) +{ + if (!a_iArgc) + throw ParserError(_T("too few arguments for function min.")); + + value_type fRes=a_afArg[0]; + for (int i=0; i<a_iArgc; ++i) + fRes = std::max(fRes, a_afArg[i]); + + return fRes; +} + +//--------------------------------------------------------------------------- +// Default value recognition callback +int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) +{ + string_type buf(a_szExpr); + std::size_t pos = buf.find_first_not_of(_T("0123456789")); + + if (pos==std::string::npos) + return 0; + + stringstream_type stream( buf.substr(0, pos ) ); + int iVal(0); + + stream >> iVal; + if (stream.fail()) + return 0; + + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + if (stream.fail()) + iEnd = stream.str().length(); + + if (iEnd==(stringstream_type::pos_type)-1) + return 0; + + *a_iPos += (int)iEnd; + *a_fVal = (value_type)iVal; + return 1; +} + +//--------------------------------------------------------------------------- +/** \brief Check a given position in the expression for the presence of + a hex value. + \param a_szExpr Pointer to the expression string + \param [in/out] a_iPos Pointer to an integer value holding the current parsing + position in the expression. + \param [out] a_fVal Pointer to the position where the detected value shall be stored. + + Hey values must be prefixed with "0x" in order to be detected properly. +*/ +int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) +{ + if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) + return 0; + + unsigned iVal(0); + + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); + + if (nPos==(stringstream_type::pos_type)0) + return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; + return 1; +} + +//--------------------------------------------------------------------------- +int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) +{ + if (a_szExpr[0]!='#') + return 0; + + unsigned iVal(0), + iBits(sizeof(iVal)*8), + i(0); + + for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i) + iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i); + + if (i==0) + return 0; + + if (i==iBits) + throw exception_type(_T("Binary to integer conversion error (overflow).")); + + *a_fVal = (unsigned)(iVal >> (iBits-i) ); + *a_iPos += i+1; + + return 1; +} + +//--------------------------------------------------------------------------- +/** \brief Constructor. + + Call ParserBase class constructor and trigger Function, Operator and Constant initialization. +*/ +ParserInt::ParserInt() + :ParserBase() +{ + AddValIdent(IsVal); // lowest priority + AddValIdent(IsBinVal); + AddValIdent(IsHexVal); // highest priority + + InitCharSets(); + InitFun(); + InitOprt(); +} + +//--------------------------------------------------------------------------- +void ParserInt::InitConst() +{ +} + +//--------------------------------------------------------------------------- +void ParserInt::InitCharSets() +{ + DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); + DefineOprtChars( _T("+-*^/?<>=!%&|~'_") ); + DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") ); +} + +//--------------------------------------------------------------------------- +/** \brief Initialize the default functions. */ +void ParserInt::InitFun() +{ + DefineFun( _T("sign"), Sign); + DefineFun( _T("abs"), Abs); + DefineFun( _T("if"), Ite); + DefineFun( _T("sum"), Sum); + DefineFun( _T("min"), Min); + DefineFun( _T("max"), Max); +} + +//--------------------------------------------------------------------------- +/** \brief Initialize operators. */ +void ParserInt::InitOprt() +{ + // disable all built in operators, not all of them useful for integer numbers + // (they don't do rounding of values) + EnableBuiltInOprt(false); + + // Disable all built in operators, they wont work with integer numbers + // since they are designed for floating point numbers + DefineInfixOprt( _T("-"), UnaryMinus); + DefineInfixOprt( _T("!"), Not); + + DefineOprt( _T("&"), LogAnd, prLOGIC); + DefineOprt( _T("|"), LogOr, prLOGIC); + DefineOprt( _T("&&"), And, prLOGIC); + DefineOprt( _T("||"), Or, prLOGIC); + + DefineOprt( _T("<"), Less, prCMP); + DefineOprt( _T(">"), Greater, prCMP); + DefineOprt( _T("<="), LessEq, prCMP); + DefineOprt( _T(">="), GreaterEq, prCMP); + DefineOprt( _T("=="), Equal, prCMP); + DefineOprt( _T("!="), NotEqual, prCMP); + + DefineOprt( _T("+"), Add, prADD_SUB); + DefineOprt( _T("-"), Sub, prADD_SUB); + + DefineOprt( _T("*"), Mul, prMUL_DIV); + DefineOprt( _T("/"), Div, prMUL_DIV); + DefineOprt( _T("%"), Mod, prMUL_DIV); + + DefineOprt( _T("^"), Pow, prPOW, oaRIGHT); + DefineOprt( _T(">>"), Shr, prMUL_DIV+1); + DefineOprt( _T("<<"), Shl, prMUL_DIV+1); +} + +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserTest.cpp b/ThirdParty/MuParser/src/muParserTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e84e38852f03290392f1d55c2326d02ce2d80785 --- /dev/null +++ b/ThirdParty/MuParser/src/muParserTest.cpp @@ -0,0 +1,1552 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "muParserTest.h" + +#include <cstdio> +#include <cmath> +#include <iostream> +#include <limits> + +#define PARSER_CONST_PI 3.141592653589793238462643 +#define PARSER_CONST_E 2.718281828459045235360287 + +using namespace std; + +/** \file + \brief This file contains the implementation of parser test cases. +*/ + +namespace mu +{ + namespace Test + { + int ParserTester::c_iCount = 0; + + //--------------------------------------------------------------------------------------------- + ParserTester::ParserTester() + :m_vTestFun() + { + AddTest(&ParserTester::TestNames); + AddTest(&ParserTester::TestSyntax); + AddTest(&ParserTester::TestPostFix); + AddTest(&ParserTester::TestInfixOprt); + AddTest(&ParserTester::TestVarConst); + AddTest(&ParserTester::TestMultiArg); + AddTest(&ParserTester::TestExpression); + AddTest(&ParserTester::TestIfThenElse); + AddTest(&ParserTester::TestInterface); + AddTest(&ParserTester::TestBinOprt); + AddTest(&ParserTester::TestException); + AddTest(&ParserTester::TestStrArg); + AddTest(&ParserTester::TestBulkMode); + + ParserTester::c_iCount = 0; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) + { + if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) + return 0; + + unsigned iVal(0); + + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); + + if (nPos==(stringstream_type::pos_type)0) + return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; + return 1; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestInterface() + { + int iStat = 0; + mu::console() << _T("testing member functions..."); + + // Test RemoveVar + value_type afVal[3] = {1,2,3}; + Parser p; + + try + { + p.DefineVar( _T("a"), &afVal[0]); + p.DefineVar( _T("b"), &afVal[1]); + p.DefineVar( _T("c"), &afVal[2]); + p.SetExpr( _T("a+b+c") ); + p.Eval(); + } + catch(...) + { + iStat += 1; // this is not supposed to happen + } + + try + { + p.RemoveVar( _T("c") ); + p.Eval(); + iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... + } + catch(...) + { + // failure is expected... + } + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestStrArg() + { + int iStat = 0; + mu::console() << _T("testing string arguments..."); + + iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash + iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true); + iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true); + // use in expressions with variables + iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true); + iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true); + // string + numeric arguments + iStat += EqnTest(_T("strfun1(\"100\")"), 100, true); + iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true); + iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true); + // string constants + iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestBulkMode() + { + int iStat = 0; + mu::console() << _T("testing bulkmode..."); + +#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ + { \ + double res[] = { R1, R2, R3, R4 }; \ + iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ + } + + // Bulk Variables for the test: + // a: 1,2,3,4 + // b: 2,2,2,2 + // c: 3,3,3,3 + // d: 5,4,3,2 + EQN_TEST_BULK("a", 1, 1, 1, 1, false) + EQN_TEST_BULK("a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) + EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) + EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) + EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) +#undef EQN_TEST_BULK + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestBinOprt() + { + int iStat = 0; + mu::console() << _T("testing binary operators..."); + + // built in operators + // xor operator + + iStat += EqnTest(_T("a++b"), 3, true); + iStat += EqnTest(_T("a ++ b"), 3, true); + iStat += EqnTest(_T("1++2"), 3, true); + iStat += EqnTest(_T("1 ++ 2"), 3, true); + iStat += EqnTest(_T("a add b"), 3, true); + iStat += EqnTest(_T("1 add 2"), 3, true); + iStat += EqnTest(_T("a<b"), 1, true); + iStat += EqnTest(_T("b>a"), 1, true); + iStat += EqnTest(_T("a>a"), 0, true); + iStat += EqnTest(_T("a<a"), 0, true); + iStat += EqnTest(_T("a>a"), 0, true); + iStat += EqnTest(_T("a<=a"), 1, true); + iStat += EqnTest(_T("a<=b"), 1, true); + iStat += EqnTest(_T("b<=a"), 0, true); + iStat += EqnTest(_T("a>=a"), 1, true); + iStat += EqnTest(_T("b>=a"), 1, true); + iStat += EqnTest(_T("a>=b"), 0, true); + + // Test logical operators, especially if user defined "&" and the internal "&&" collide + iStat += EqnTest(_T("1 && 1"), 1, true); + iStat += EqnTest(_T("1 && 0"), 0, true); + iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true); + iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true); + //iStat += EqnTest(_T("12 and 255"), 12, true); + //iStat += EqnTest(_T("12 and 0"), 0, true); + iStat += EqnTest(_T("12 & 255"), 12, true); + iStat += EqnTest(_T("12 & 0"), 0, true); + iStat += EqnTest(_T("12&255"), 12, true); + iStat += EqnTest(_T("12&0"), 0, true); + + // Assignment operator + iStat += EqnTest(_T("a = b"), 2, true); + iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); + iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true); + iStat += EqnTest(_T("(a=b)*2"), 4, true); + iStat += EqnTest(_T("2*(a=b)"), 4, true); + iStat += EqnTest(_T("2*(a=b+1)"), 6, true); + iStat += EqnTest(_T("(a=b+1)*2"), 6, true); + iStat += EqnTest(_T("a=c, a*10"), 30, true); + + iStat += EqnTest(_T("2^2^3"), 256, true); + iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); + + // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3 + iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); + + // Test user defined binary operators + iStat += EqnTestInt(_T("1 | 2"), 3, true); + iStat += EqnTestInt(_T("1 || 2"), 1, true); + iStat += EqnTestInt(_T("123 & 456"), 72, true); + iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true); + iStat += EqnTestInt(_T("1 && 0"), 0, true); + iStat += EqnTestInt(_T("123 && 456"), 1, true); + iStat += EqnTestInt(_T("1 << 3"), 8, true); + iStat += EqnTestInt(_T("8 >> 3"), 1, true); + iStat += EqnTestInt(_T("9 / 4"), 2, true); + iStat += EqnTestInt(_T("9 % 4"), 1, true); + iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true); + iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true); + iStat += EqnTestInt(_T("-10+1"), -9, true); + iStat += EqnTestInt(_T("1+2*3"), 7, true); + iStat += EqnTestInt(_T("const1 != const2"), 1, true); + iStat += EqnTestInt(_T("const1 != const2"), 0, false); + iStat += EqnTestInt(_T("const1 == const2"), 0, true); + iStat += EqnTestInt(_T("const1 == 1"), 1, true); + iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false); + iStat += EqnTestInt(_T("const1 < const2"), 1, true); + iStat += EqnTestInt(_T("const2 > const1"), 1, true); + iStat += EqnTestInt(_T("const1 <= 1"), 1, true); + iStat += EqnTestInt(_T("const2 >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true); + iStat += EqnTestInt(_T("a != b"), 1, true); + iStat += EqnTestInt(_T("a != b"), 0, false); + iStat += EqnTestInt(_T("a == b"), 0, true); + iStat += EqnTestInt(_T("a == 1"), 1, true); + iStat += EqnTestInt(_T("10*(a == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(a | b)"), 6, true); + iStat += EqnTestInt(_T("2*(a | b)"), 7, false); + iStat += EqnTestInt(_T("a < b"), 1, true); + iStat += EqnTestInt(_T("b > a"), 1, true); + iStat += EqnTestInt(_T("a <= 1"), 1, true); + iStat += EqnTestInt(_T("b >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(a + b)"), 6, true); + iStat += EqnTestInt(_T("2*(a - b)"), -2, true); + iStat += EqnTestInt(_T("a + (a << b)"), 5, true); + iStat += EqnTestInt(_T("-2^2"), -4, true); + iStat += EqnTestInt(_T("3--a"), 4, true); + iStat += EqnTestInt(_T("3+-3^2"), -6, true); + + // Test reading of hex values: + iStat += EqnTestInt(_T("0xff"), 255, true); + iStat += EqnTestInt(_T("10+0xff"), 265, true); + iStat += EqnTestInt(_T("0xff+10"), 265, true); + iStat += EqnTestInt(_T("10*0xff"), 2550, true); + iStat += EqnTestInt(_T("0xff*10"), 2550, true); + iStat += EqnTestInt(_T("10+0xff+1"), 266, true); + iStat += EqnTestInt(_T("1+0xff+10"), 266, true); + +// incorrect: '^' is yor here, not power +// iStat += EqnTestInt("-(1+2)^2", -9, true); +// iStat += EqnTestInt("-1^3", -1, true); + + // Test precedence + // a=1, b=2, c=3 + iStat += EqnTestInt(_T("a + b * c"), 7, true); + iStat += EqnTestInt(_T("a * b + c"), 5, true); + iStat += EqnTestInt(_T("a<b && b>10"), 0, true); + iStat += EqnTestInt(_T("a<b && b<10"), 1, true); + + iStat += EqnTestInt(_T("a + b << c"), 17, true); + iStat += EqnTestInt(_T("a << b + c"), 7, true); + iStat += EqnTestInt(_T("c * b < a"), 0, true); + iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true); + iStat += EqnTestInt(_T("2^2^3"), 256, true); + + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + /** \brief Check muParser name restriction enforcement. */ + int ParserTester::TestNames() + { + int iStat= 0, + iErr = 0; + + mu::console() << "testing name restriction enforcement..."; + + Parser p; + + #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \ + iErr = 0; \ + ParserTester::c_iCount++; \ + try \ + { \ + p.Define##DOMAIN(EXPR, ARG); \ + } \ + catch(Parser::exception_type&) \ + { \ + iErr = (FAIL==false) ? 0 : 1; \ + } \ + iStat += iErr; + + // constant names + PARSER_THROWCHECK(Const, false, _T("0a"), 1) + PARSER_THROWCHECK(Const, false, _T("9a"), 1) + PARSER_THROWCHECK(Const, false, _T("+a"), 1) + PARSER_THROWCHECK(Const, false, _T("-a"), 1) + PARSER_THROWCHECK(Const, false, _T("a-"), 1) + PARSER_THROWCHECK(Const, false, _T("a*"), 1) + PARSER_THROWCHECK(Const, false, _T("a?"), 1) + PARSER_THROWCHECK(Const, true, _T("a"), 1) + PARSER_THROWCHECK(Const, true, _T("a_min"), 1) + PARSER_THROWCHECK(Const, true, _T("a_min0"), 1) + PARSER_THROWCHECK(Const, true, _T("a_min9"), 1) + // variable names + value_type a; + p.ClearConst(); + PARSER_THROWCHECK(Var, false, _T("123abc"), &a) + PARSER_THROWCHECK(Var, false, _T("9a"), &a) + PARSER_THROWCHECK(Var, false, _T("0a"), &a) + PARSER_THROWCHECK(Var, false, _T("+a"), &a) + PARSER_THROWCHECK(Var, false, _T("-a"), &a) + PARSER_THROWCHECK(Var, false, _T("?a"), &a) + PARSER_THROWCHECK(Var, false, _T("!a"), &a) + PARSER_THROWCHECK(Var, false, _T("a+"), &a) + PARSER_THROWCHECK(Var, false, _T("a-"), &a) + PARSER_THROWCHECK(Var, false, _T("a*"), &a) + PARSER_THROWCHECK(Var, false, _T("a?"), &a) + PARSER_THROWCHECK(Var, true, _T("a"), &a) + PARSER_THROWCHECK(Var, true, _T("a_min"), &a) + PARSER_THROWCHECK(Var, true, _T("a_min0"), &a) + PARSER_THROWCHECK(Var, true, _T("a_min9"), &a) + PARSER_THROWCHECK(Var, false, _T("a_min9"), 0) + // Postfix operators + // fail + PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1) + PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1) + PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0) + // pass + PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("_"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("#"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("&&"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("||"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("&"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("|"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("++"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("--"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("?>"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1) + // Binary operator + // The following must fail with builtin operators activated + // p.EnableBuiltInOp(true); -> this is the default + p.ClearPostfixOprt(); + PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2) + // without activated built in operators it should work + p.EnableBuiltInOprt(false); + PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) + #undef PARSER_THROWCHECK + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestSyntax() + { + int iStat = 0; + mu::console() << _T("testing syntax engine..."); + + iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition + + iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula + iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets + iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or" + iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket + iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator + iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator + iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("--2"), 0, false); // double sign + iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token + iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function + iStat += EqnTest(_T("5t6"), 0, false); // unknown token + iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token + iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula + iStat += EqnTest(_T(",3"), 0, false); // unexpected comma + iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma + iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args + iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args + iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestVarConst() + { + int iStat = 0; + mu::console() << _T("testing variable/constant detection..."); + + // Test if the result changes when a variable changes + iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 ); + iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 ); + + // distinguish constants with same basename + iStat += EqnTest( _T("const"), 1, true); + iStat += EqnTest( _T("const1"), 2, true); + iStat += EqnTest( _T("const2"), 3, true); + iStat += EqnTest( _T("2*const"), 2, true); + iStat += EqnTest( _T("2*const1"), 4, true); + iStat += EqnTest( _T("2*const2"), 6, true); + iStat += EqnTest( _T("2*const+1"), 3, true); + iStat += EqnTest( _T("2*const1+1"), 5, true); + iStat += EqnTest( _T("2*const2+1"), 7, true); + iStat += EqnTest( _T("const"), 0, false); + iStat += EqnTest( _T("const1"), 0, false); + iStat += EqnTest( _T("const2"), 0, false); + + // distinguish variables with same basename + iStat += EqnTest( _T("a"), 1, true); + iStat += EqnTest( _T("aa"), 2, true); + iStat += EqnTest( _T("2*a"), 2, true); + iStat += EqnTest( _T("2*aa"), 4, true); + iStat += EqnTest( _T("2*a-1"), 1, true); + iStat += EqnTest( _T("2*aa-1"), 3, true); + + // custom value recognition + iStat += EqnTest( _T("0xff"), 255, true); + iStat += EqnTest( _T("0x97 + 0xff"), 406, true); + + // Finally test querying of used variables + try + { + int idx; + mu::Parser p; + mu::value_type vVarVal[] = { 1, 2, 3, 4, 5}; + p.DefineVar( _T("a"), &vVarVal[0]); + p.DefineVar( _T("b"), &vVarVal[1]); + p.DefineVar( _T("c"), &vVarVal[2]); + p.DefineVar( _T("d"), &vVarVal[3]); + p.DefineVar( _T("e"), &vVarVal[4]); + + // Test lookup of defined variables + // 4 used variables + p.SetExpr( _T("a+b+c+d") ); + mu::varmap_type UsedVar = p.GetUsedVar(); + int iCount = (int)UsedVar.size(); + if (iCount!=4) + throw false; + + // the next check will fail if the parser + // erroneously creates new variables internally + if (p.GetVar().size()!=5) + throw false; + + mu::varmap_type::const_iterator item = UsedVar.begin(); + for (idx=0; item!=UsedVar.end(); ++item) + { + if (&vVarVal[idx++]!=item->second) + throw false; + } + + // Test lookup of undefined variables + p.SetExpr( _T("undef1+undef2+undef3") ); + UsedVar = p.GetUsedVar(); + iCount = (int)UsedVar.size(); + if (iCount!=3) + throw false; + + // the next check will fail if the parser + // erroneously creates new variables internally + if (p.GetVar().size()!=5) + throw false; + + for (item = UsedVar.begin(); item!=UsedVar.end(); ++item) + { + if (item->second!=0) + throw false; // all pointers to undefined variables must be null + } + + // 1 used variables + p.SetExpr( _T("a+b") ); + UsedVar = p.GetUsedVar(); + iCount = (int)UsedVar.size(); + if (iCount!=2) throw false; + item = UsedVar.begin(); + for (idx=0; item!=UsedVar.end(); ++item) + if (&vVarVal[idx++]!=item->second) throw false; + + } + catch(...) + { + iStat += 1; + } + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestMultiArg() + { + int iStat = 0; + mu::console() << _T("testing multiarg functions..."); + + // Compound expressions + iStat += EqnTest( _T("1,2,3"), 3, true); + iStat += EqnTest( _T("a,b,c"), 3, true); + iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true); + iStat += EqnTest( _T("1,\n2,\n3"), 3, true); + iStat += EqnTest( _T("a,\nb,\nc"), 3, true); + iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true); + iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true); + iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true); + iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true); + + // picking the right argument + iStat += EqnTest( _T("f1of1(1)"), 1, true); + iStat += EqnTest( _T("f1of2(1, 2)"), 1, true); + iStat += EqnTest( _T("f2of2(1, 2)"), 2, true); + iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true); + iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true); + iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true); + iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true); + iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true); + iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true); + iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true); + iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true); + iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true); + iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true); + iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true); + iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true); + // Too few arguments / Too many arguments + iStat += EqnTest( _T("1+ping()"), 11, true); + iStat += EqnTest( _T("ping()+1"), 11, true); + iStat += EqnTest( _T("2*ping()"), 20, true); + iStat += EqnTest( _T("ping()*2"), 20, true); + iStat += EqnTest( _T("ping(1,2)"), 0, false); + iStat += EqnTest( _T("1+ping(1,2)"), 0, false); + iStat += EqnTest( _T("f1of1(1,2)"), 0, false); + iStat += EqnTest( _T("f1of1()"), 0, false); + iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false); + iStat += EqnTest( _T("f1of2(1)"), 0, false); + iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false); + iStat += EqnTest( _T("f1of3(1)"), 0, false); + iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false); + iStat += EqnTest( _T("f1of4(1)"), 0, false); + iStat += EqnTest( _T("(1,2,3)"), 0, false); + iStat += EqnTest( _T("1,2,3"), 0, false); + iStat += EqnTest( _T("(1*a,2,3)"), 0, false); + iStat += EqnTest( _T("1,2*a,3"), 0, false); + + // correct calculation of arguments + iStat += EqnTest( _T("min(a, 1)"), 1, true); + iStat += EqnTest( _T("min(3*2, 1)"), 1, true); + iStat += EqnTest( _T("min(3*2, 1)"), 6, false); + iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true); + iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true); + iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true); + iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true); + iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true); + iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true); + + // functions with Variable argument count + iStat += EqnTest( _T("sum(a)"), 1, true); + iStat += EqnTest( _T("sum(1,2,3)"), 6, true); + iStat += EqnTest( _T("sum(a,b,c)"), 6, true); + iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true); + iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true); + iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true); + iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true); + iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true); + iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true); + iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true); + iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true); + iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true); + + // some failures + iStat += EqnTest( _T("sum()"), 0, false); + iStat += EqnTest( _T("sum(,)"), 0, false); + iStat += EqnTest( _T("sum(1,2,)"), 0, false); + iStat += EqnTest( _T("sum(,1,2)"), 0, false); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + //--------------------------------------------------------------------------- + int ParserTester::TestInfixOprt() + { + int iStat(0); + mu::console() << "testing infix operators..."; + + iStat += EqnTest( _T("+1"), +1, true); + iStat += EqnTest( _T("-(+1)"), -1, true); + iStat += EqnTest( _T("-(+1)*2"), -2, true); + iStat += EqnTest( _T("-(+2)*sqrt(4)"), -4, true); + iStat += EqnTest( _T("3-+a"), 2, true); + iStat += EqnTest( _T("+1*3"), 3, true); + + iStat += EqnTest( _T("-1"), -1, true); + iStat += EqnTest( _T("-(-1)"), 1, true); + iStat += EqnTest( _T("-(-1)*2"), 2, true); + iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true); + iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true); + iStat += EqnTest( _T("-a"), -1, true); + iStat += EqnTest( _T("-(a)"), -1, true); + iStat += EqnTest( _T("-(-a)"), 1, true); + iStat += EqnTest( _T("-(-a)*2"), 2, true); + iStat += EqnTest( _T("-(8)"), -8, true); + iStat += EqnTest( _T("-8"), -8, true); + iStat += EqnTest( _T("-(2+1)"), -3, true); + iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true); + iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true); + iStat += EqnTest( _T("-sin(8)"), -0.989358, true); + iStat += EqnTest( _T("3-(-a)"), 4, true); + iStat += EqnTest( _T("3--a"), 4, true); + iStat += EqnTest( _T("-1*3"), -3, true); + + // Postfix / infix priorities + iStat += EqnTest( _T("~2#"), 8, true); + iStat += EqnTest( _T("~f1of1(2)#"), 8, true); + iStat += EqnTest( _T("~(b)#"), 8, true); + iStat += EqnTest( _T("(~b)#"), 12, true); + iStat += EqnTest( _T("~(2#)"), 8, true); + iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true); + // + iStat += EqnTest( _T("-2^2"),-4, true); + iStat += EqnTest( _T("-(a+b)^2"),-9, true); + iStat += EqnTest( _T("(-3)^2"),9, true); + iStat += EqnTest( _T("-(-2^2)"),4, true); + iStat += EqnTest( _T("3+-3^2"),-6, true); + // The following assumes use of sqr as postfix operator ("§") together + // with a sign operator of low priority: + iStat += EqnTest( _T("-2'"), -4, true); + iStat += EqnTest( _T("-(1+1)'"),-4, true); + iStat += EqnTest( _T("2+-(1+1)'"),-2, true); + iStat += EqnTest( _T("2+-2'"), -2, true); + // This is the classic behaviour of the infix sign operator (here: "$") which is + // now deprecated: + iStat += EqnTest( _T("$2^2"),4, true); + iStat += EqnTest( _T("$(a+b)^2"),9, true); + iStat += EqnTest( _T("($3)^2"),9, true); + iStat += EqnTest( _T("$($2^2)"),-4, true); + iStat += EqnTest( _T("3+$3^2"),12, true); + + // infix operators sharing the first few characters + iStat += EqnTest( _T("~ 123"), 123+2, true); + iStat += EqnTest( _T("~~ 123"), 123+2, true); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + //--------------------------------------------------------------------------- + int ParserTester::TestPostFix() + { + int iStat = 0; + mu::console() << _T("testing postfix operators..."); + + // application + iStat += EqnTest( _T("3{m}+5"), 5.003, true); + iStat += EqnTest( _T("1000{m}"), 1, true); + iStat += EqnTest( _T("1000 {m}"), 1, true); + iStat += EqnTest( _T("(a){m}"), 1e-3, true); + iStat += EqnTest( _T("a{m}"), 1e-3, true); + iStat += EqnTest( _T("a {m}"), 1e-3, true); + iStat += EqnTest( _T("-(a){m}"), -1e-3, true); + iStat += EqnTest( _T("-2{m}"), -2e-3, true); + iStat += EqnTest( _T("-2 {m}"), -2e-3, true); + iStat += EqnTest( _T("f1of1(1000){m}"), 1, true); + iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true); + iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true); + iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true); + iStat += EqnTest( _T("2+(a*1000){m}"), 3, true); + + // can postfix operators "m" und "meg" be told apart properly? + iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true); + + // some incorrect results + iStat += EqnTest( _T("1000{m}"), 0.1, false); + iStat += EqnTest( _T("(a){m}"), 2, false); + // failure due to syntax checking + iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition + iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); + iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS); + iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS); + + iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestExpression() + { + int iStat = 0; + mu::console() << _T("testing expression samples..."); + + value_type b = 2; + + // Optimization + iStat += EqnTest( _T("2*b*5"), 20, true); + iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true); + iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true); + + // Addition auf cmVARMUL + iStat += EqnTest( _T("3+b"), b+3, true); + iStat += EqnTest( _T("b+3"), b+3, true); + iStat += EqnTest( _T("b*3+2"), b*3+2, true); + iStat += EqnTest( _T("3*b+2"), b*3+2, true); + iStat += EqnTest( _T("2+b*3"), b*3+2, true); + iStat += EqnTest( _T("2+3*b"), b*3+2, true); + iStat += EqnTest( _T("b+3*b"), b+3*b, true); + iStat += EqnTest( _T("3*b+b"), b+3*b, true); + + iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true); + iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true); + + iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true); + iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true); + + // operator precedences + iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true); + iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true); + iStat += EqnTest( _T("1+2*3"), 7, true); + iStat += EqnTest( _T("1+2*3"), 7, true); + iStat += EqnTest( _T("(1+2)*3"), 9, true); + iStat += EqnTest( _T("(1+2)*(-3)"), -9, true); + iStat += EqnTest( _T("2/4"), 0.5, true); + + iStat += EqnTest( _T("exp(ln(7))"), 7, true); + iStat += EqnTest( _T("e^ln(7)"), 7, true); + iStat += EqnTest( _T("e^(ln(7))"), 7, true); + iStat += EqnTest( _T("(e^(ln(7)))"), 7, true); + iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true); + iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true); + iStat += EqnTest( _T("10^log(5)"), pow(10.0, log(5.0)), true); + iStat += EqnTest( _T("10^log10(5)"), 5, true); + iStat += EqnTest( _T("2^log2(4)"), 4, true); + iStat += EqnTest( _T("-(sin(0)+1)"), -1, true); + iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true); + + iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true); + iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true); + iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true); + iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true); + + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))") + _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/") + _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-") + _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6") + _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e") + _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true); + + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e") + _T(")+a)))*2.77)"), -2.16995656, true); + + // long formula (Reference: Matlab) + iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + + //--------------------------------------------------------------------------- + int ParserTester::TestIfThenElse() + { + int iStat = 0; + mu::console() << _T("testing if-then-else operator..."); + + // Test error detection + iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE); + iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE); + iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE); + iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE); + iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON); + iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON); + iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON); + iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN); + + iStat += EqnTest(_T("1 ? 128 : 255"), 128, true); + iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true); + iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true); + iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true); + iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true); + iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true); + iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true); + iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true); + iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true); + iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true); + iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true); + iStat += EqnTest(_T("(a<b) ? c : d"), 3, true); + iStat += EqnTest(_T("(a>b) ? c : d"), -2, true); + + iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true); + + iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true); + iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true); + iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true); + iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true); + iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true); + iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true); + iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true); + iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true); + iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true); + iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true); + iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true); + iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true); + iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true); + + // todo: auch für muParserX hinzufügen! + iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true); + + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true); + iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true); + iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true); + iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true); + + // assignment operators + iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true); + iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true); + iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true); + iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true); + iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true); + iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true); + iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true); // a should not change its value due to lazy calculation + + iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true); + iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true); + iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true); + iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true); + + iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true); + iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true); + iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true); + iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestException() + { + int iStat = 0; + mu::console() << _T("testing error codes..."); + + iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); + iStat += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS); + iStat += ThrowTest(_T("()"), ecUNEXPECTED_PARENS); + iStat += ThrowTest(_T("3+()"), ecUNEXPECTED_PARENS); + iStat += ThrowTest(_T("sin(3,4)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS); + iStat += ThrowTest(_T("(1+2"), ecMISSING_PARENS); + iStat += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL); + iStat += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN); + iStat += ThrowTest(_T("a+b+c=10"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest(_T("a=b=3"), ecUNEXPECTED_OPERATOR); + +#if defined(MUP_MATH_EXCEPTIONS) + // divide by zero whilst constant folding + iStat += ThrowTest(_T("1/0"), ecDIV_BY_ZERO); + // square root of a negative number + iStat += ThrowTest(_T("sqrt(-1)"), ecDOMAIN_ERROR); + // logarithms of zero + iStat += ThrowTest(_T("ln(0)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log2(0)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log10(0)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log(0)"), ecDOMAIN_ERROR); + // logarithms of negative values + iStat += ThrowTest(_T("ln(-1)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log2(-1)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log10(-1)"), ecDOMAIN_ERROR); + iStat += ThrowTest(_T("log(-1)"), ecDOMAIN_ERROR); +#endif + + // functions without parameter + iStat += ThrowTest( _T("3+ping(2)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("3+ping(a+2)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("3+ping(sin(a)+2)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("3+ping(1+sin(a))"), ecTOO_MANY_PARAMS); + + // String function related + iStat += ThrowTest( _T("valueof(\"xxx\")"), 999, false); + iStat += ThrowTest( _T("valueof()"), ecUNEXPECTED_PARENS); + iStat += ThrowTest( _T("1+valueof(\"abc\""), ecMISSING_PARENS); + iStat += ThrowTest( _T("valueof(\"abc\""), ecMISSING_PARENS); + iStat += ThrowTest( _T("valueof(\"abc"), ecUNTERMINATED_STRING); + iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("valueof(3)"), ecSTRING_EXPECTED); + iStat += ThrowTest( _T("sin(\"abc\")"), ecVAL_EXPECTED); + iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"), 999, false); + iStat += ThrowTest( _T("\"hello world\""), ecSTR_RESULT); + iStat += ThrowTest( _T("(\"hello world\")"), ecSTR_RESULT); + iStat += ThrowTest( _T("\"abcd\"+100"), ecOPRT_TYPE_CONFLICT); + iStat += ThrowTest( _T("\"a\"+\"b\""), ecOPRT_TYPE_CONFLICT); + iStat += ThrowTest( _T("strfun1(\"100\",3)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("strfun2(\"100\",3,5)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("strfun2(\"100\")"), ecTOO_FEW_PARAMS); + iStat += ThrowTest( _T("strfun3(\"100\",6)"), ecTOO_FEW_PARAMS); + iStat += ThrowTest( _T("strfun2(1,1)"), ecSTRING_EXPECTED); + iStat += ThrowTest( _T("strfun2(a,1)"), ecSTRING_EXPECTED); + iStat += ThrowTest( _T("strfun2(1,1,1)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("strfun2(a,1,1)"), ecTOO_MANY_PARAMS); + iStat += ThrowTest( _T("strfun3(1,2,3)"), ecSTRING_EXPECTED); + iStat += ThrowTest( _T("strfun3(1, \"100\",3)"), ecSTRING_EXPECTED); + iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"), ecVAL_EXPECTED); + iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"), ecVAL_EXPECTED); + iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"), ecTOO_MANY_PARAMS); + + // assignment operator + iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR); + + // <ibg 20090529> + // this is now legal, for reference see: + // https://sourceforge.net/forum/message.php?msg_id=7411373 + // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); + // </ibg> + + iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT); + + if (iStat==0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + //--------------------------------------------------------------------------- + void ParserTester::AddTest(testfun_type a_pFun) + { + m_vTestFun.push_back(a_pFun); + } + + //--------------------------------------------------------------------------- + void ParserTester::Run() + { + int iStat = 0; + try + { + for (int i=0; i<(int)m_vTestFun.size(); ++i) + iStat += (this->*m_vTestFun[i])(); + } + catch(Parser::exception_type &e) + { + mu::console() << "\n" << e.GetMsg() << endl; + mu::console() << e.GetToken() << endl; + Abort(); + } + catch(std::exception &e) + { + mu::console() << e.what() << endl; + Abort(); + } + catch(...) + { + mu::console() << "Internal error"; + Abort(); + } + + if (iStat==0) + { + mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl; + } + else + { + mu::console() << "Test failed with " << iStat + << " errors (" << ParserTester::c_iCount + << " expressions)" << endl; + } + ParserTester::c_iCount = 0; + } + + + //--------------------------------------------------------------------------- + int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) + { + ParserTester::c_iCount++; + + try + { + value_type fVal[] = {1,1,1}; + Parser p; + + p.DefineVar( _T("a"), &fVal[0]); + p.DefineVar( _T("b"), &fVal[1]); + p.DefineVar( _T("c"), &fVal[2]); + p.DefinePostfixOprt( _T("{m}"), Milli); + p.DefinePostfixOprt( _T("m"), Milli); + p.DefineFun( _T("ping"), Ping); + p.DefineFun( _T("valueof"), ValueOf); + p.DefineFun( _T("strfun1"), StrFun1); + p.DefineFun( _T("strfun2"), StrFun2); + p.DefineFun( _T("strfun3"), StrFun3); + p.SetExpr(a_str); + p.Eval(); + } + catch(ParserError &e) + { + // output the formula in case of an failed test + if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) ) + { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str + << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")") + << _T(" Expected:") << a_iErrc; + } + + return (a_iErrc==e.GetCode()) ? 0 : 1; + } + + // if a_bFail==false no exception is expected + bool bRet((a_bFail==false) ? 0 : 1); + if (bRet==1) + { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str + << _T(" did evaluate; Expected error:") << a_iErrc; + } + + return bRet; + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate a tet expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTestWithVarChange(const string_type &a_str, + double a_fVar1, + double a_fRes1, + double a_fVar2, + double a_fRes2) + { + ParserTester::c_iCount++; + + try + { + value_type fVal[2] = {-999, -999 }; // should be equal + + Parser p; + value_type var = 0; + + // variable + p.DefineVar( _T("a"), &var); + p.SetExpr(a_str); + + var = a_fVar1; + fVal[0] = p.Eval(); + + var = a_fVar2; + fVal[1] = p.Eval(); + + if ( fabs(a_fRes1-fVal[0]) > 0.0000000001) + throw std::runtime_error("incorrect result (first pass)"); + + if ( fabs(a_fRes2-fVal[1]) > 0.0000000001) + throw std::runtime_error("incorrect result (second pass)"); + } + catch(Parser::exception_type &e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); + return 1; + } + catch(std::exception &e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); + return 1; // always return a failure since this exception is not expected + } + catch(...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + return 1; // exceptions other than ParserException are not allowed + } + + return 0; + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate a tet expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + int iRet(0); + value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different + + try + { + std::auto_ptr<Parser> p1; + Parser p2, p3; // three parser objects + // they will be used for testing copy and assignment operators + // p1 is a pointer since i'm going to delete it in order to test if + // parsers after copy construction still refer to members of it. + // !! If this is the case this function will crash !! + + p1.reset(new mu::Parser()); + // Add constants + p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI); + p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E); + p1->DefineConst( _T("const"), 1); + p1->DefineConst( _T("const1"), 2); + p1->DefineConst( _T("const2"), 3); + // string constants + p1->DefineStrConst( _T("str1"), _T("1.11")); + p1->DefineStrConst( _T("str2"), _T("2.22")); + // variables + value_type vVarVal[] = { 1, 2, 3, -2}; + p1->DefineVar( _T("a"), &vVarVal[0]); + p1->DefineVar( _T("aa"), &vVarVal[1]); + p1->DefineVar( _T("b"), &vVarVal[1]); + p1->DefineVar( _T("c"), &vVarVal[2]); + p1->DefineVar( _T("d"), &vVarVal[3]); + + // custom value ident functions + p1->AddValIdent(&ParserTester::IsHexVal); + + // functions + p1->DefineFun( _T("ping"), Ping); + p1->DefineFun( _T("f1of1"), f1of1); // one parameter + p1->DefineFun( _T("f1of2"), f1of2); // two parameter + p1->DefineFun( _T("f2of2"), f2of2); + p1->DefineFun( _T("f1of3"), f1of3); // three parameter + p1->DefineFun( _T("f2of3"), f2of3); + p1->DefineFun( _T("f3of3"), f3of3); + p1->DefineFun( _T("f1of4"), f1of4); // four parameter + p1->DefineFun( _T("f2of4"), f2of4); + p1->DefineFun( _T("f3of4"), f3of4); + p1->DefineFun( _T("f4of4"), f4of4); + p1->DefineFun( _T("f1of5"), f1of5); // five parameter + p1->DefineFun( _T("f2of5"), f2of5); + p1->DefineFun( _T("f3of5"), f3of5); + p1->DefineFun( _T("f4of5"), f4of5); + p1->DefineFun( _T("f5of5"), f5of5); + + // binary operators + p1->DefineOprt( _T("add"), add, 0); + p1->DefineOprt( _T("++"), add, 0); + p1->DefineOprt( _T("&"), land, prLAND); + + // sample functions + p1->DefineFun( _T("min"), Min); + p1->DefineFun( _T("max"), Max); + p1->DefineFun( _T("sum"), Sum); + p1->DefineFun( _T("valueof"), ValueOf); + p1->DefineFun( _T("atof"), StrToFloat); + p1->DefineFun( _T("strfun1"), StrFun1); + p1->DefineFun( _T("strfun2"), StrFun2); + p1->DefineFun( _T("strfun3"), StrFun3); + p1->DefineFun( _T("lastArg"), LastArg); + p1->DefineFun( _T("firstArg"), FirstArg); + p1->DefineFun( _T("order"), FirstArg); + + // infix / postfix operator + // Note: Identifiers used here do not have any meaning + // they are mere placeholders to test certain features. + p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority + p1->DefineInfixOprt( _T("~"), plus2); // high priority + p1->DefineInfixOprt( _T("~~"), plus2); + p1->DefinePostfixOprt( _T("{m}"), Milli); + p1->DefinePostfixOprt( _T("{M}"), Mega); + p1->DefinePostfixOprt( _T("m"), Milli); + p1->DefinePostfixOprt( _T("meg"), Mega); + p1->DefinePostfixOprt( _T("#"), times3); + p1->DefinePostfixOprt( _T("'"), sqr); + p1->SetExpr(a_str); + + // Test bytecode integrity + // String parsing and bytecode parsing must yield the same result + fVal[0] = p1->Eval(); // result from stringparsing + fVal[1] = p1->Eval(); // result from bytecode + if (fVal[0]!=fVal[1]) + throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") ); + + // Test copy and assignment operators + try + { + // Test copy constructor + std::vector<mu::Parser> vParser; + vParser.push_back(*(p1.get())); + mu::Parser p2 = vParser[0]; // take parser from vector + + // destroy the originals from p2 + vParser.clear(); // delete the vector + p1.reset(0); + + fVal[2] = p2.Eval(); + + // Test assignment operator + // additionally disable Optimizer this time + mu::Parser p3; + p3 = p2; + p3.EnableOptimizer(false); + fVal[3] = p3.Eval(); + + // Test Eval function for multiple return values + // use p2 since it has the optimizer enabled! + int nNum; + value_type *v = p2.Eval(nNum); + fVal[4] = v[nNum-1]; + } + catch(std::exception &e) + { + mu::console() << _T("\n ") << e.what() << _T("\n"); + } + + // limited floating point accuracy requires the following test + bool bCloseEnough(true); + for (unsigned i=0; i<sizeof(fVal)/sizeof(value_type); ++i) + { + bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.00001)); + + // The tests equations never result in infinity, if they do thats a bug. + // reference: + // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825 + #pragma warning(push) + #pragma warning(disable:4127) + if (std::numeric_limits<value_type>::has_infinity) + #pragma warning(pop) + { + bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity()); + } + } + + iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; + + + if (iRet==1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes + << _T(" ;calculated: ") << fVal[0] << _T(",") + << fVal[1] << _T(",") + << fVal[2] << _T(",") + << fVal[3] << _T(",") + << fVal[4] << _T(")."); + } + } + catch(Parser::exception_type &e) + { + if (a_fPass) + { + if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998) + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); + else + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); + return 1; + } + } + catch(std::exception &e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); + return 1; // always return a failure since this exception is not expected + } + catch(...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + return 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + + value_type vVarVal[] = {1, 2, 3}; // variable values + int iRet(0); + + try + { + value_type fVal[2] = {-99, -999}; // results: initially should be different + ParserInt p; + p.DefineConst( _T("const1"), 1); + p.DefineConst( _T("const2"), 2); + p.DefineVar( _T("a"), &vVarVal[0]); + p.DefineVar( _T("b"), &vVarVal[1]); + p.DefineVar( _T("c"), &vVarVal[2]); + + p.SetExpr(a_str); + fVal[0] = p.Eval(); // result from stringparsing + fVal[1] = p.Eval(); // result from bytecode + + if (fVal[0]!=fVal[1]) + throw Parser::exception_type( _T("Bytecode corrupt.") ); + + iRet = ( (a_fRes==fVal[0] && a_fPass) || + (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1; + if (iRet==1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes + << _T(" ;calculated: ") << fVal[0]<< _T(")."); + } + } + catch(Parser::exception_type &e) + { + if (a_fPass) + { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; + } + } + catch(...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + iRet = 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + /** \brief Test an expression in Bulk Mode. */ + int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) + { + ParserTester::c_iCount++; + + // Define Bulk Variables + int nBulkSize = 4; + value_type vVariableA[] = { 1, 2, 3, 4 }; // variable values + value_type vVariableB[] = { 2, 2, 2, 2 }; // variable values + value_type vVariableC[] = { 3, 3, 3, 3 }; // variable values + value_type vResults[] = { 0, 0, 0, 0 }; // variable values + int iRet(0); + + try + { + Parser p; + p.DefineConst(_T("const1"), 1); + p.DefineConst(_T("const2"), 2); + p.DefineVar(_T("a"), vVariableA); + p.DefineVar(_T("b"), vVariableB); + p.DefineVar(_T("c"), vVariableC); + + p.SetExpr(a_str); + p.Eval(vResults, nBulkSize); + + bool bCloseEnough(true); + for (int i = 0; i < nBulkSize; ++i) + { + bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); + } + + iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; + if (iRet == 1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") + << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); + } + } + catch (Parser::exception_type &e) + { + if (a_fPass) + { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; + } + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + iRet = 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + /** \brief Internal error in test class Test is going to be aborted. */ + void ParserTester::Abort() const + { + mu::console() << _T("Test failed (internal error in test class)") << endl; + while (!getchar()); + exit(-1); + } + } // namespace test +} // namespace mu diff --git a/ThirdParty/MuParser/src/muParserTokenReader.cpp b/ThirdParty/MuParser/src/muParserTokenReader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de15ff043e6f0ea9133d404fd2375512785a7b8a --- /dev/null +++ b/ThirdParty/MuParser/src/muParserTokenReader.cpp @@ -0,0 +1,958 @@ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ + / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ + | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ + Copyright (C) 2013 Ingo Berg + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include <cassert> +#include <cstdio> +#include <cstring> +#include <map> +#include <stack> +#include <string> + +#include "muParserTokenReader.h" +#include "muParserBase.h" + +/** \file + \brief This file contains the parser token reader implementation. +*/ + + +namespace mu +{ + + // Forward declaration + class ParserBase; + + //--------------------------------------------------------------------------- + /** \brief Copy constructor. + + \sa Assign + \throw nothrow + */ + ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) + { + Assign(a_Reader); + } + + //--------------------------------------------------------------------------- + /** \brief Assignment operator. + + Self assignment will be suppressed otherwise #Assign is called. + + \param a_Reader Object to copy to this token reader. + \throw nothrow + */ + ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) + { + if (&a_Reader!=this) + Assign(a_Reader); + + return *this; + } + + //--------------------------------------------------------------------------- + /** \brief Assign state of a token reader to this token reader. + + \param a_Reader Object from which the state should be copied. + \throw nothrow + */ + void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) + { + m_pParser = a_Reader.m_pParser; + m_strFormula = a_Reader.m_strFormula; + m_iPos = a_Reader.m_iPos; + m_iSynFlags = a_Reader.m_iSynFlags; + + m_UsedVar = a_Reader.m_UsedVar; + m_pFunDef = a_Reader.m_pFunDef; + m_pConstDef = a_Reader.m_pConstDef; + m_pVarDef = a_Reader.m_pVarDef; + m_pStrVarDef = a_Reader.m_pStrVarDef; + m_pPostOprtDef = a_Reader.m_pPostOprtDef; + m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; + m_pOprtDef = a_Reader.m_pOprtDef; + m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; + m_vIdentFun = a_Reader.m_vIdentFun; + m_pFactory = a_Reader.m_pFactory; + m_pFactoryData = a_Reader.m_pFactoryData; + m_iBrackets = a_Reader.m_iBrackets; + m_cArgSep = a_Reader.m_cArgSep; + m_fZero = a_Reader.m_fZero; + m_lastTok = a_Reader.m_lastTok; + } + + //--------------------------------------------------------------------------- + /** \brief Constructor. + + Create a Token reader and bind it to a parser object. + + \pre [assert] a_pParser may not be NULL + \post #m_pParser==a_pParser + \param a_pParent Parent parser object of the token reader. + */ + ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) + :m_pParser(a_pParent) + ,m_strFormula() + ,m_iPos(0) + ,m_iSynFlags(0) + ,m_bIgnoreUndefVar(false) + ,m_pFunDef(NULL) + ,m_pPostOprtDef(NULL) + ,m_pInfixOprtDef(NULL) + ,m_pOprtDef(NULL) + ,m_pConstDef(NULL) + ,m_pStrVarDef(NULL) + ,m_pVarDef(NULL) + ,m_pFactory(NULL) + ,m_pFactoryData(NULL) + ,m_vIdentFun() + ,m_UsedVar() + ,m_fZero(0) + ,m_iBrackets(0) + ,m_lastTok() + ,m_cArgSep(',') + { + assert(m_pParser); + SetParent(m_pParser); + } + + //--------------------------------------------------------------------------- + /** \brief Create instance of a ParserTokenReader identical with this + and return its pointer. + + This is a factory method the calling function must take care of the object destruction. + + \return A new ParserTokenReader object. + \throw nothrow + */ + ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const + { + std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this)); + ptr->SetParent(a_pParent); + return ptr.release(); + } + + //--------------------------------------------------------------------------- + ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok) + { + m_lastTok = tok; + return m_lastTok; + } + + //--------------------------------------------------------------------------- + void ParserTokenReader::AddValIdent(identfun_type a_pCallback) + { + // Use push_front is used to give user defined callbacks a higher priority than + // the built in ones. Otherwise reading hex numbers would not work + // since the "0" in "0xff" would always be read first making parsing of + // the rest impossible. + // reference: + // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956 + m_vIdentFun.push_front(a_pCallback); + } + + //--------------------------------------------------------------------------- + void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) + { + m_pFactory = a_pFactory; + m_pFactoryData = pUserData; + } + + //--------------------------------------------------------------------------- + /** \brief Return the current position of the token reader in the formula string. + + \return #m_iPos + \throw nothrow + */ + int ParserTokenReader::GetPos() const + { + return m_iPos; + } + + //--------------------------------------------------------------------------- + /** \brief Return a reference to the formula. + + \return #m_strFormula + \throw nothrow + */ + const string_type& ParserTokenReader::GetExpr() const + { + return m_strFormula; + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing the used variables only. */ + varmap_type& ParserTokenReader::GetUsedVar() + { + return m_UsedVar; + } + + //--------------------------------------------------------------------------- + /** \brief Initialize the token Reader. + + Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. + \pre [assert] triggered if a_szFormula==0 + */ + void ParserTokenReader::SetFormula(const string_type &a_strFormula) + { + m_strFormula = a_strFormula; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Set Flag that controls behaviour in case of undefined variables being found. + + If true, the parser does not throw an exception if an undefined variable is found. + otherwise it does. This variable is used internally only! + It suppresses a "undefined variable" exception in GetUsedVar(). + Those function should return a complete list of variables including + those the are not defined by the time of it's call. + */ + void ParserTokenReader::IgnoreUndefVar(bool bIgnore) + { + m_bIgnoreUndefVar = bIgnore; + } + + //--------------------------------------------------------------------------- + /** \brief Reset the token reader to the start of the formula. + + The syntax flags will be reset to a value appropriate for the + start of a formula. + \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR + \throw nothrow + \sa ESynCodes + */ + void ParserTokenReader::ReInit() + { + m_iPos = 0; + m_iSynFlags = sfSTART_OF_LINE; + m_iBrackets = 0; + m_UsedVar.clear(); + m_lastTok = token_type(); + } + + //--------------------------------------------------------------------------- + /** \brief Read the next token from the string. */ + ParserTokenReader::token_type ParserTokenReader::ReadNextToken() + { + assert(m_pParser); + + const char_type *szFormula = m_strFormula.c_str(); + token_type tok; + + // Ignore all non printable characters when reading the expression + while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) + ++m_iPos; + + if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula + if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator + if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token + if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens + if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators + if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens + if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens + if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables + if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens + if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators + if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators + + // Check String for undefined variable token. Done only if a + // flag is set indicating to ignore undefined variables. + // This is a way to conditionally avoid an error if + // undefined variables occur. + // (The GetUsedVar function must suppress the error for + // undefined variables in order to collect all variable + // names including the undefined ones.) + if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) + return SaveBeforeReturn(tok); + + // Check for unknown token + // + // !!! From this point on there is no exit without an exception possible... + // + string_type strTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); + if (iEnd!=m_iPos) + Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + + Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); + return token_type(); // never reached + } + + //--------------------------------------------------------------------------- + void ParserTokenReader::SetParent(ParserBase *a_pParent) + { + m_pParser = a_pParent; + m_pFunDef = &a_pParent->m_FunDef; + m_pOprtDef = &a_pParent->m_OprtDef; + m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; + m_pPostOprtDef = &a_pParent->m_PostOprtDef; + m_pVarDef = &a_pParent->m_VarDef; + m_pStrVarDef = &a_pParent->m_StrVarDef; + m_pConstDef = &a_pParent->m_ConstDef; + } + + //--------------------------------------------------------------------------- + /** \brief Extract all characters that belong to a certain charset. + + \param a_szCharSet [in] Const char array of the characters allowed in the token. + \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. + \param a_iPos [in] Position in the string from where to start reading. + \return The Position of the first character not listed in a_szCharSet. + \throw nothrow + */ + int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, + string_type &a_sTok, + int a_iPos) const + { + int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos); + + if (iEnd==(int)string_type::npos) + iEnd = (int)m_strFormula.length(); + + // Assign token string if there was something found + if (a_iPos!=iEnd) + a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd); + + return iEnd; + } + + //--------------------------------------------------------------------------- + /** \brief Check Expression for the presence of a binary operator token. + + Userdefined binary operator "++" gives inconsistent parsing result for + the equations "a++b" and "a ++ b" if alphabetic characters are allowed + in operator tokens. To avoid this this function checks specifically + for operator tokens. + */ + int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, + int a_iPos) const + { + // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6 + int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos); + if (iEnd==(int)string_type::npos) + iEnd = (int)m_strFormula.length(); + + // Assign token string if there was something found + if (a_iPos!=iEnd) + { + a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); + return iEnd; + } + else + { + // There is still the chance of having to deal with an operator consisting exclusively + // of alphabetic characters. + return ExtractToken(MUP_CHARS, a_sTok, a_iPos); + } + } + + //--------------------------------------------------------------------------- + /** \brief Check if a built in operator or other token can be found + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. + \return true if an operator token has been found. + */ + bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) + { + const char_type **const pOprtDef = m_pParser->GetOprtDef(), + *const szFormula = m_strFormula.c_str(); + + // Compare token with function and operator strings + // check string for operator/function + for (int i=0; pOprtDef[i]; i++) + { + std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) ); + if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) ) + { + switch(i) + { + //case cmAND: + //case cmOR: + //case cmXOR: + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + //if (len!=sTok.length()) + // continue; + + // The assignment operator need special treatment + if (i==cmASSIGN && m_iSynFlags & noASSIGN) + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + + if (!m_pParser->HasBuiltInOprt()) continue; + if (m_iSynFlags & noOPT) + { + // Maybe its an infix operator not an operator + // Both operator types can share characters in + // their identifiers + if ( IsInfixOpTok(a_Tok) ) + return true; + + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + } + + m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; + break; + + case cmBO: + if (m_iSynFlags & noBO) + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + + if (m_lastTok.GetCode()==cmFUNC) + m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; + else + m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE; + + ++m_iBrackets; + break; + + case cmBC: + if (m_iSynFlags & noBC) + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; + + if (--m_iBrackets<0) + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + break; + + case cmELSE: + if (m_iSynFlags & noELSE) + Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; + break; + + case cmIF: + if (m_iSynFlags & noIF) + Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; + break; + + default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... + Error(ecINTERNAL_ERROR); + } // switch operator id + + m_iPos += (int)len; + a_Tok.Set( (ECmdCode)i, pOprtDef[i] ); + return true; + } // if operator string found + } // end of for all operator strings + + return false; + } + + //--------------------------------------------------------------------------- + bool ParserTokenReader::IsArgSep(token_type &a_Tok) + { + const char_type* szFormula = m_strFormula.c_str(); + + if (szFormula[m_iPos]==m_cArgSep) + { + // copy the separator into null terminated string + char_type szSep[2]; + szSep[0] = m_cArgSep; + szSep[1] = 0; + + if (m_iSynFlags & noARG_SEP) + Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); + + m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; + m_iPos++; + a_Tok.Set(cmARG_SEP, szSep); + return true; + } + + return false; + } + + //--------------------------------------------------------------------------- + /** \brief Check for End of Formula. + + \return true if an end of formula is found false otherwise. + \param a_Tok [out] If an eof is found the corresponding token will be stored there. + \throw nothrow + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok + */ + bool ParserTokenReader::IsEOF(token_type &a_Tok) + { + const char_type* szFormula = m_strFormula.c_str(); + + // check for EOF + if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) + { + if ( m_iSynFlags & noEND ) + Error(ecUNEXPECTED_EOF, m_iPos); + + if (m_iBrackets>0) + Error(ecMISSING_PARENS, m_iPos, _T(")")); + + m_iSynFlags = 0; + a_Tok.Set(cmEND); + return true; + } + + return false; + } + + //--------------------------------------------------------------------------- + /** \brief Check if a string position contains a unary infix operator. + \return true if a function token has been found false otherwise. + */ + bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) + { + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos); + if (iEnd==m_iPos) + return false; + + // iterate over all postfix operator strings + funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin(); + for ( ; it!=m_pInfixOprtDef->rend(); ++it) + { + if (sTok.find(it->first)!=0) + continue; + + a_Tok.Set(it->second, it->first); + m_iPos += (int)it->first.length(); + + if (m_iSynFlags & noINFIXOP) + Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; + return true; + } + + return false; + +/* + a_Tok.Set(item->second, sTok); + m_iPos = (int)iEnd; + + if (m_iSynFlags & noINFIXOP) + Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; + return true; +*/ + } + + //--------------------------------------------------------------------------- + /** \brief Check whether the token at a given position is a function token. + \param a_Tok [out] If a value token is found it will be placed here. + \throw ParserException if Syntaxflags do not allow a function at a_iPos + \return true if a function token has been found false otherwise. + \pre [assert] m_pParser!=0 + */ + bool ParserTokenReader::IsFunTok(token_type &a_Tok) + { + string_type strTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); + if (iEnd==m_iPos) + return false; + + funmap_type::const_iterator item = m_pFunDef->find(strTok); + if (item==m_pFunDef->end()) + return false; + + // Check if the next sign is an opening bracket + const char_type *szFormula = m_strFormula.c_str(); + if (szFormula[iEnd]!='(') + return false; + + a_Tok.Set(item->second, strTok); + + m_iPos = (int)iEnd; + if (m_iSynFlags & noFUN) + Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); + + m_iSynFlags = noANY ^ noBO; + return true; + } + + //--------------------------------------------------------------------------- + /** \brief Check if a string position contains a binary operator. + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. + \return true if an operator token has been found. + */ + bool ParserTokenReader::IsOprt(token_type &a_Tok) + { + const char_type *const szExpr = m_strFormula.c_str(); + string_type strTok; + + int iEnd = ExtractOperatorToken(strTok, m_iPos); + if (iEnd==m_iPos) + return false; + + // Check if the operator is a built in operator, if so ignore it here + const char_type **const pOprtDef = m_pParser->GetOprtDef(); + for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) + { + if (string_type(pOprtDef[i])==strTok) + return false; + } + + // Note: + // All tokens in oprt_bin_maptype are have been sorted by their length + // Long operators must come first! Otherwise short names (like: "add") that + // are part of long token names (like: "add123") will be found instead + // of the long ones. + // Length sorting is done with ascending length so we use a reverse iterator here. + funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin(); + for ( ; it!=m_pOprtDef->rend(); ++it) + { + const string_type &sID = it->first; + if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) ) + { + a_Tok.Set(it->second, strTok); + + // operator was found + if (m_iSynFlags & noOPT) + { + // An operator was found but is not expected to occur at + // this position of the formula, maybe it is an infix + // operator, not a binary operator. Both operator types + // can share characters in their identifiers. + if ( IsInfixOpTok(a_Tok) ) + return true; + else + { + // nope, no infix operator + return false; + //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + } + + } + + m_iPos += (int)sID.length(); + m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; + return true; + } + } + + return false; + } + + //--------------------------------------------------------------------------- + /** \brief Check if a string position contains a unary post value operator. */ + bool ParserTokenReader::IsPostOpTok(token_type &a_Tok) + { + // <ibg 20110629> Do not check for postfix operators if they are not allowed at + // the current expression index. + // + // This will fix the bug reported here: + // + // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979 + // + if (m_iSynFlags & noPOSTOP) + return false; + // </ibg> + + // Tricky problem with equations like "3m+5": + // m is a postfix operator, + is a valid sign for postfix operators and + // for binary operators parser detects "m+" as operator string and + // finds no matching postfix operator. + // + // This is a special case so this routine slightly differs from the other + // token readers. + + // Test if there could be a postfix operator + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos); + if (iEnd==m_iPos) + return false; + + // iterate over all postfix operator strings + funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin(); + for ( ; it!=m_pPostOprtDef->rend(); ++it) + { + if (sTok.find(it->first)!=0) + continue; + + a_Tok.Set(it->second, sTok); + m_iPos += (int)it->first.length(); + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; + return true; + } + + return false; + } + + //--------------------------------------------------------------------------- + /** \brief Check whether the token at a given position is a value token. + + Value tokens are either values or constants. + + \param a_Tok [out] If a value token is found it will be placed here. + \return true if a value token has been found. + */ + bool ParserTokenReader::IsValTok(token_type &a_Tok) + { + assert(m_pConstDef); + assert(m_pParser); + + string_type strTok; + value_type fVal(0); + int iEnd(0); + + // 2.) Check for user defined constant + // Read everything that could be a constant name + iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); + if (iEnd!=m_iPos) + { + valmap_type::const_iterator item = m_pConstDef->find(strTok); + if (item!=m_pConstDef->end()) + { + m_iPos = iEnd; + a_Tok.SetVal(item->second, strTok); + + if (m_iSynFlags & noVAL) + Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + } + + // 3.call the value recognition functions provided by the user + // Call user defined value recognition functions + std::list<identfun_type>::const_iterator item = m_vIdentFun.begin(); + for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item) + { + int iStart = m_iPos; + if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 ) + { + // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 + strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart); + + if (m_iSynFlags & noVAL) + Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + + a_Tok.SetVal(fVal, strTok); + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + } + + return false; + } + + //--------------------------------------------------------------------------- + /** \brief Check wheter a token at a given position is a variable token. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a variable token has been found. + */ + bool ParserTokenReader::IsVarTok(token_type &a_Tok) + { + if (m_pVarDef->empty()) + return false; + + string_type strTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); + if (iEnd==m_iPos) + return false; + + varmap_type::const_iterator item = m_pVarDef->find(strTok); + if (item==m_pVarDef->end()) + return false; + + if (m_iSynFlags & noVAR) + Error(ecUNEXPECTED_VAR, m_iPos, strTok); + + m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); + + m_iPos = iEnd; + a_Tok.SetVar(item->second, strTok); + m_UsedVar[item->first] = item->second; // Add variable to used-var-list + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR; + +// Zur Info hier die SynFlags von IsVal(): +// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + + //--------------------------------------------------------------------------- + bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) + { + if (!m_pStrVarDef || m_pStrVarDef->empty()) + return false; + + string_type strTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); + if (iEnd==m_iPos) + return false; + + strmap_type::const_iterator item = m_pStrVarDef->find(strTok); + if (item==m_pStrVarDef->end()) + return false; + + if (m_iSynFlags & noSTR) + Error(ecUNEXPECTED_VAR, m_iPos, strTok); + + m_iPos = iEnd; + if (!m_pParser->m_vStringVarBuf.size()) + Error(ecINTERNAL_ERROR); + + a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() ); + + m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP); + return true; + } + + + //--------------------------------------------------------------------------- + /** \brief Check wheter a token at a given position is an undefined variable. + + \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. + \return true if a variable token has been found. + \throw nothrow + */ + bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) + { + string_type strTok; + int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) ); + if ( iEnd==m_iPos ) + return false; + + if (m_iSynFlags & noVAR) + { + // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the + // token identifier. + // related bug report: + // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 + Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); + } + + // If a factory is available implicitely create new variables + if (m_pFactory) + { + value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData); + a_Tok.SetVar(fVar, strTok ); + + // Do not use m_pParser->DefineVar( strTok, fVar ); + // in order to define the new variable, it will clear the + // m_UsedVar array which will kill previously defined variables + // from the list + // This is safe because the new variable can never override an existing one + // because they are checked first! + (*m_pVarDef)[strTok] = fVar; + m_UsedVar[strTok] = fVar; // Add variable to used-var-list + } + else + { + a_Tok.SetVar((value_type*)&m_fZero, strTok); + m_UsedVar[strTok] = 0; // Add variable to used-var-list + } + + m_iPos = iEnd; + + // Call the variable factory in order to let it define a new parser variable + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR; + return true; + } + + + //--------------------------------------------------------------------------- + /** \brief Check wheter a token at a given position is a string. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a string token has been found. + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok + \throw nothrow + */ + bool ParserTokenReader::IsString(token_type &a_Tok) + { + if (m_strFormula[m_iPos]!='"') + return false; + + string_type strBuf(&m_strFormula[m_iPos+1]); + std::size_t iEnd(0), iSkip(0); + + // parser over escaped '\"' end replace them with '"' + for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd)) + { + if (strBuf[iEnd-1]!='\\') break; + strBuf.replace(iEnd-1, 2, _T("\"") ); + iSkip++; + } + + if (iEnd==string_type::npos) + Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") ); + + string_type strTok(strBuf.begin(), strBuf.begin()+iEnd); + + if (m_iSynFlags & noSTR) + Error(ecUNEXPECTED_STR, m_iPos, strTok); + + m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer + a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); + + m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen + m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND ); + + return true; + } + + //--------------------------------------------------------------------------- + /** \brief Create an error containing the parse error position. + + This function will create an Parser Exception object containing the error text and its position. + + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws thats the only purpose of this function. + */ + void ParserTokenReader::Error( EErrorCodes a_iErrc, + int a_iPos, + const string_type &a_sTok) const + { + m_pParser->Error(a_iErrc, a_iPos, a_sTok); + } + + //--------------------------------------------------------------------------- + void ParserTokenReader::SetArgSep(char_type cArgSep) + { + m_cArgSep = cArgSep; + } + + //--------------------------------------------------------------------------- + char_type ParserTokenReader::GetArgSep() const + { + return m_cArgSep; + } +} // namespace mu + diff --git a/VirtualFluidsBasics/IncludsList.cmake b/VirtualFluidsBasics/IncludsList.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5655947dded019800743d8de0791848fe45b7366 --- /dev/null +++ b/VirtualFluidsBasics/IncludsList.cmake @@ -0,0 +1,6 @@ +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics/geometry3d) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics/basics/container) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics/basics/objects) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics/basics/utilities) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsBasics/basics/writer) \ No newline at end of file diff --git a/VirtualFluidsBasics/VirtualFluidsBasics.cmake b/VirtualFluidsBasics/VirtualFluidsBasics.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a0e1b3a2014fc15c09fd1773c4cad64c5646350d --- /dev/null +++ b/VirtualFluidsBasics/VirtualFluidsBasics.cmake @@ -0,0 +1,6 @@ +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/geometry3d/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/basics/objects/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/basics/utilities/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/basics/container/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/basics/writer/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/IncludsList.cmake) \ No newline at end of file diff --git a/VirtualFluidsBasics/basics/container/CMakePackage.txt b/VirtualFluidsBasics/basics/container/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..b2d974b49ca72178a8823a1e2e06fc7087205c88 --- /dev/null +++ b/VirtualFluidsBasics/basics/container/CMakePackage.txt @@ -0,0 +1,4 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) + + diff --git a/VirtualFluidsBasics/basics/container/CbArray2D.h b/VirtualFluidsBasics/basics/container/CbArray2D.h new file mode 100644 index 0000000000000000000000000000000000000000..575ef2f5403ea35a40a4f214b32829e3d7c39efc --- /dev/null +++ b/VirtualFluidsBasics/basics/container/CbArray2D.h @@ -0,0 +1,413 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CbArray2D.h +//! \ingroup container +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef CBARRAY2D_H +#define CBARRAY2D_H + +#include <iomanip> + +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbEqual.h> +#include <algorithm> +#include <typeinfo> + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// IndexClasses + +//IndexerX2X1: +// 4 5 6 +// Array 1 2 3 --> vector 1 2 3 4 5 6 +//optimaler schleifendurchlauf +//for(alle X2) +// for(alle X1) +class IndexerX2X1 +{ +public: + typedef int size_type; +public: + inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const + { + return nx1* x2 + x1; + } + inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const + { + return nx1* x2; + } +}; + +//IndexerX1X2: +// 4 5 6 +// Array 1 2 3 --> vector 1 4 2 5 3 6 +//optimaler schleifendurchlauf +//for(alle X1) +// for(alle X2) +class IndexerX1X2 +{ +public: + typedef int size_type; +public: + inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1,const size_type& nx2) const + { + return nx2* x1+ x2; + } + inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const + { + return nx2* x1; + } +}; + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// CbArray2D +////////////////////////////////////////////////////////////////////////// +//! \brief 2D Array +//! \details the data is stored in a vector +//! +//! Rangecheck active, if: +//! +//! -debug : not defined "NO_CB_RANGECHECK" +//! +//! -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK" +////////////////////////////////////////////////////////////////////////// +template<typename T, typename IndexClass = IndexerX2X1> +class CbArray2D +{ +public: + typedef T value_type; + typedef IndexClass indexer_type; + typedef typename IndexClass::size_type size_type; + typedef typename std::vector< value_type >::reference reference; + typedef typename std::vector< value_type >::const_reference const_reference; + typedef typename std::vector< value_type >::pointer pointer; + typedef typename std::vector< value_type >::const_pointer const_pointer; + +private: + template< typename value_type2, typename IndexClass2 > friend class CbArray2D; + +public: + /*=======================================================================*/ + CbArray2D() + { + this->resize(0,0); + } + /*=======================================================================*/ + CbArray2D(const size_type& nx2, const size_type& nx1) + { + this->resize(nx2,nx1); + } + /*=======================================================================*/ + CbArray2D(const size_type& nx2, const size_type& nx1, const value_type& val) + { + this->resize(nx2,nx1,val); + } + /*=======================================================================*/ + CbArray2D(const size_type& uniformDimensionSize /*nx1==nx2*/) + { + this->resize(uniformDimensionSize,uniformDimensionSize); + } + /*=======================================================================*/ + //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird) + CbArray2D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2) + { + assert( (nx1*nx2)==vec.size() ); + this->data.swap(vec); + this->resize(nx1,nx2); + } + /*=======================================================================*/ + CbArray2D(const CbArray2D& src) + : nx1(src.nx1) + , nx2(src.nx2) + , data(src.data) + { + } + /*=======================================================================*/ + template< typename value_type2 > + CbArray2D(const CbArray2D< value_type2 >& src) + : nx1(src.nx1) + , nx2(src.nx2) + { + //Sourcedaten kopieren + this->data.resize( src.data.size() ); + for(std::size_t i=0; i<data.size(); ++i) + this->data[i] = src.data[i]; + } + /*=======================================================================*/ + virtual ~CbArray2D() + { + //vector wird automatisch zerstoert + } + /*=======================================================================*/ + CbArray2D& operator= (const CbArray2D& rhs) + { + if(this == &rhs) return *this; + + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + + //Laenge anpassen + this->data.resize(rhs.data.size()); + //gespeicherte Datenelemente loeschen + this->data.clear(); + + //Sourcedaten kopieren + this->data = rhs.data; + + return *this; + } + /*=======================================================================*/ + //durch value_type2 kann man z.B. ein float array einem double array zuweisen! + template< typename value_type2, typename IndexClass2 > + CbArray2D& operator= (const CbArray2D< value_type2, IndexClass2 >& rhs) + { + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + + //gespeicherte Datenelemente loeschen + this->data.clear(); + //Laenge anpassen + this->data.resize(rhs.data.size()); + + //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + //ACHTUNG: für diese Konvertierung muss bei Klassen der demenstrechende operator + // implementiert sein, e.g.: class value_type2 {public: inline operator value_type2() const { return value_type2(); } + for(int x1=0; x1<this->nx1; x1++) + for(int x2=0; x2<this->nx2; x2++) + this->operator()(x1,x2) = static_cast< value_type >( rhs.operator()(x1,x2) ); + + return *this; + } + /*=======================================================================*/ + bool operator== (const CbArray2D& rhs) const + { + if( this == &rhs ) return true; + + if( this->nx1!=rhs.nx1 + || this->nx2!=rhs.nx2 + || this->data.size() != rhs.data.size() ) + { + return false; + } + + return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() ); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator== (const CbArray2D< value_type2, IndexClass2 >& rhs) const + { + if( this->data.size() != rhs.data.size() ) return false; + + //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + for(int x1=0; x1<this->nx1; x1++) + for(int x2=0; x2<this->nx2; x2++) + if( !isUbEqual(this->operator()(x1,x2), rhs.operator()(x1,x2)) ) + return false; + + return true; + } + /*=======================================================================*/ + bool operator!= (const CbArray2D& rhs) const + { + return !(*this==rhs); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator!= (const CbArray2D< value_type2, IndexClass2 >& rhs) const + { + return !(*this==rhs); + } + /*=======================================================================*/ + reference operator() (const size_type& x1,const size_type& x2) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + + return this->data[indexer.getIndex(x1,x2,nx1,nx2)]; + } + /*=======================================================================*/ + const_reference operator() (const size_type& x1,const size_type& x2) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + + return this->data[indexer.getIndex(x1,x2,nx1,nx2)]; + } + /*=======================================================================*/ + pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)]; + } + /*=======================================================================*/ + const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)]; + } + /*=======================================================================*/ + void setObject(const size_type& x1,const size_type& x2,const value_type& value) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + this->data[indexer.getIndex(x1,x2,nx1,nx2)] = value; + } + /*=======================================================================*/ + reference getObject(const size_type& x1, const size_type& x2) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + return this->data[indexer.getIndex(x1,x2,nx1,nx2)] ; + } + /*=======================================================================*/ + typename std::vector<value_type>::const_reference getObject(const size_type& x1, const size_type& x2) const + { + return this->operator()(x1,x2); + } + /*=======================================================================*/ + bool isEmpty() const { return data.empty(); } + size_type getNX1() const { return this->nx1; } + size_type getNX2() const { return this->nx2; } + /*=======================================================================*/ + void reset(const T& val) + { + std::fill( this->data.begin(), this->data.end(), val ); + } + /*=======================================================================*/ + std::string toString() const + { + std::stringstream text; + for(size_type x2=0; x2<this->nx2; x2++) + { + for(size_type x1=0; x1<this->nx1; x1++) + { + //hier kommts zum Konflikt ab und an ... + text<<this->getObject(x1,x2)<<", "; + } + text<<"\n"; + } + + return text.str(); + } + /*=======================================================================*/ + std::string getInfo() const + { + std::stringstream text; + text<<"CbArray2D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >"; + text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<")"; + return text.str(); + } + /*=======================================================================*/ + void resize(const size_type& uniformDimensionSize) + { + this->resize(uniformDimensionSize,uniformDimensionSize); + } + /*=======================================================================*/ + void resize(const size_type& nx1,const size_type& nx2) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->data.resize(nx1*nx2); + } + /*=======================================================================*/ + void resize(const size_type& nx1, const size_type& nx2, const value_type& initVal ) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->data.resize(nx1*nx2,initVal); + } + /*=======================================================================*/ + void clear() + { + this->nx1 = 0; + this->nx2 = 0; + this->data.clear(); + } + /*=======================================================================*/ + std::vector< value_type >& getDataVector() { return this->data; } + /*=======================================================================*/ + const std::vector< value_type >& getDataVector() const { return this->data; } + /*=======================================================================*/ + inline size_type getDataVectorIndex(const size_type& x1, const size_type& x2) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) ); + #endif + + return indexer.getIndex(x1,x2,nx1,nx2); + } + +protected: + /*=======================================================================*/ + //success -> true + //else -> false + inline bool indicesInRange(const size_type& x1, const size_type& x2) const + { + if( x1 < 0 || x1 >= this->nx1 + || x2 < 0 || x2 >= this->nx2 ) + { + return false; + } + return true; + } + /*=======================================================================*/ + std::string getExceptionErrorString(const size_type& x1, const size_type& x2) const + { + std::stringstream out("index out of range - "); + out<<"("<<x1<<","<<x2<<") not in ("<<nx1<<","<<nx2<<")"; + return out.str(); + } + /*=======================================================================*/ + +protected: + size_type nx1; + size_type nx2; + indexer_type indexer; + std::vector< value_type > data; +}; + +#endif //CBARRAY2D_H diff --git a/VirtualFluidsBasics/basics/container/CbArray3D.h b/VirtualFluidsBasics/basics/container/CbArray3D.h new file mode 100644 index 0000000000000000000000000000000000000000..575b0cb84019bdd0241698d4f8e861ccd9aa2159 --- /dev/null +++ b/VirtualFluidsBasics/basics/container/CbArray3D.h @@ -0,0 +1,468 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CbArray3D.h +//! \ingroup container +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef CBARRAY3D_H +#define CBARRAY3D_H + +#include <iomanip> + +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbEqual.h> +#include <algorithm> +#include <typeinfo> +#include "PointerDefinitions.h" + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// IndexClasses + +//IndexerX3X2X1: +// 4 5 6 10 11 12 +// Array ebene A 1 2 3 ebene B 7 8 9 --> vector 1 2 3 4 5 6 7 8 9 10 11 12 +//x1-reihen "liegen am stueck" im speicher +//optimaler schleifendurchlauf +//for(alle X3) +// for(alle X2) +// for(alle X1) +class IndexerX3X2X1// FunctorX1SortedForX1X2Plane +{ +public: + typedef size_t size_type; +public: + inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx1 * ( nx2 * x3 + x2) + x1 ; + } + inline std::size_t getStartIndexOfSortedArray( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx1 * ( nx2 * x3 + x2); + } +}; + +//IndexerX1X2X3: +// 4 5 6 10 11 12 +// Array ebene A 1 2 3 ebene B 7 8 9 --> +//optimaler schleifendurchlauf +//for(alle X1) +// for(alle X2) +// for(alle X3) +class IndexerX1X2X3 //FunctorX3SortedForX3X2Plane +{ +public: + typedef size_t size_type; +public: + inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx3 * ( nx2 * x1 + x2) + x3 ; + } + inline std::size_t getStartIndexOfSortedArray( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx3 * ( nx2 * x1 + x2); + } +}; + +//IndexerX2X1X3: +// 4 5 6 10 11 12 +// Array ebene A 1 2 3 ebene B 7 8 9 --> vector 1 7 2 8 3 9 4 10 5 11 6 12 +//optimaler schleifendurchlauf +//for(alle X2) +// for(alle X1) +// for(alle X3) +class IndexerX2X1X3 +{ +public: + typedef size_t size_type; +public: + inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx3* ( nx1 * x2 + x1) + x3 ; + } + inline std::size_t getStartIndexOfSortedArray( const size_type& x1 , const size_type& x2 , const size_type& x3 + , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const + { + return nx3* ( nx1 * x2 + x1); + } +}; + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// CbArray3D +////////////////////////////////////////////////////////////////////////// +//! \brief 3D Array +//! \details The data is stored in a vector +//! +//! Rangecheck active, if: +//! +//! -debug : not defined "NO_CB_RANGECHECK" +//! +//! -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK" +////////////////////////////////////////////////////////////////////////// +template<typename T, typename IndexClass = IndexerX3X2X1> +class CbArray3D +{ +public: + typedef SPtr< CbArray3D <T,IndexClass> > CbArray3DPtr; + + typedef T value_type; + typedef IndexClass indexer_type; + typedef typename IndexClass::size_type size_type; + typedef typename std::vector< value_type >::reference reference; + typedef typename std::vector< value_type >::const_reference const_reference; + typedef typename std::vector< value_type >::pointer pointer; + typedef typename std::vector< value_type >::const_pointer const_pointer; + +private: + template< typename value_type2, typename IndexClass2 > friend class CbArray3D; + +public: + /*=======================================================================*/ + CbArray3D() + { + this->resize(0,0,0); + } + /*=======================================================================*/ + CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const value_type& val) + { + this->resize(nx1,nx2,nx3,val); + } + /*=======================================================================*/ + CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3) + { + this->resize(nx1,nx2,nx3); + } + /*=======================================================================*/ + CbArray3D(const size_type& uniformDimensionSize /*nx1==nx2==nx3*/) + { + this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); + } + /*=======================================================================*/ + //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird) + CbArray3D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3) + { + assert( (nx1*nx2*nx3)==vec.size() ); + this->data.swap(vec); + this->resize(nx1,nx2,nx3); + } + /*=======================================================================*/ + CbArray3D(const CbArray3D& src) + : nx1(src.nx1) + , nx2(src.nx2) + , nx3(src.nx3) + , data(src.data) + { + } + /*=======================================================================*/ + template< typename value_type2 > + CbArray3D(const CbArray3D< value_type2 >& src) + : nx1(src.nx1) + , nx2(src.nx2) + , nx3(src.nx3) + { + //Sourcedaten kopieren + this->data.resize( src.data.size() ); + for(std::size_t i=0; i<data.size(); ++i) + this->data[i] = src.data[i]; + } + /*=======================================================================*/ + virtual ~CbArray3D() + { + //vector wird automatisch zerstoert + } + /*=======================================================================*/ + CbArray3D& operator= (const CbArray3D& rhs) + { + if(this == &rhs) return *this; + + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + this->nx3 = rhs.nx3; + + //gespeicherte Datenelemente loeschen + //Laenge anpassen + this->data.resize(rhs.data.size()); + //gespeicherte Datenelemente loeschen + this->data.clear(); + + //Sourcedaten kopieren + this->data = rhs.data; + + return *this; + } + /*=======================================================================*/ + //durch value_type2 kann man z.B. ein float array einer double array zuweisen! + template< typename value_type2, typename IndexClass2 > + CbArray3D& operator= (const CbArray3D< value_type2, IndexClass2 >& rhs) + { + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + this->nx3 = rhs.nx3; + + //gespeicherte Datenelemente loeschen + this->data.clear(); + //Laenge anpassen + this->data.resize(rhs.data.size()); + + //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + for(int x3=0; x3<this->nx3; x3++) + for(int x2=0; x2<this->nx2; x2++) + for(int x1=0; x1<this->nx1; x1++) + this->operator()(x1,x2,x3) = static_cast< value_type >( rhs.operator()(x1,x2,x3) ); + + return *this; + } + /*=======================================================================*/ + bool operator== (const CbArray3D& rhs) const + { + if(this == &rhs) return true; + + if( this->nx1!=rhs.nx1 + || this->nx2!=rhs.nx2 + || this->nx3!=rhs.nx3 + || this->data.size() != rhs.data.size() ) + { + return false; + } + + return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() ); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator== (const CbArray3D< value_type2, IndexClass2 >& rhs) const + { + if( this->data.size() != rhs.data.size() ) return false; + + //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + for(int x3=0; x3<this->nx3; x3++) + for(int x2=0; x2<this->nx2; x2++) + for(int x1=0; x1<this->nx1; x1++) + if( !isUbEqual(this->operator()(x1,x2,x3), rhs.operator()(x1,x2,x3)) ) + return false; + + return true; + } + /*=======================================================================*/ + bool operator!= (const CbArray3D& src) const + { + return !(*this==src); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator!= (const CbArray3D< value_type2, IndexClass2 >& rhs) const + { + return !(*this==rhs); + } + /*=======================================================================*/ + reference operator() (const size_type& x1, const size_type& x2, const size_type& x3) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ]; + } + /*=======================================================================*/ + const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ]; + } + /*=======================================================================*/ + pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)]; + } + /*=======================================================================*/ + const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)]; + } + /*=======================================================================*/ + void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const value_type& value) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] = value; + } + /*=======================================================================*/ + reference getObject(const size_type& x1, const size_type& x2, const size_type& x3) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] ; + } + /*=======================================================================*/ + const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3) const + { + return (*this)(x1,x2,x3); + } + /*=======================================================================*/ + bool isEmpty() const { return data.empty(); } + size_type getNX1() const { return this->nx1; } + size_type getNX2() const { return this->nx2; } + size_type getNX3() const { return this->nx3; } + /*=======================================================================*/ + void reset(const value_type& val) + { + std::fill( this->data.begin(), this->data.end(), val ); + } + /*=======================================================================*/ + std::string toString() const + { + std::stringstream text; + for(size_type x1=0; x1<this->nx1; x1++) + { + for(size_type x2=0; x2<this->nx2; x2++) + { + for(size_type x3=0; x3<this->nx3; x3++) + { + text<<(*this)(x1,x2,x3)<<", "; + } + text<<std::endl; + } + text<<std::endl<<std::endl; + } + + return text.str(); + } + /*=======================================================================*/ + std::string getInfo() const + { + std::stringstream text; + text<<"CbArray3D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >"; + text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<")"; + return text.str(); + } + /*=======================================================================*/ + void resize(const int& uniformDimensionSize) + { + this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); + } + /*=======================================================================*/ + void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->nx3 = nx3; + this->data.resize(nx1*nx2*nx3); + } + /*=======================================================================*/ + void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3,const value_type& val) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->nx3 = nx3; + this->data.resize(nx1*nx2*nx3,val); + } + /*=======================================================================*/ + void clear() + { + this->nx1 = 0; + this->nx2 = 0; + this->nx3 = 0; + this->data.clear(); + } + /*=======================================================================*/ + std::vector< value_type >& getDataVector() { return this->data; } + /*=======================================================================*/ + const std::vector< value_type >& getDataVector() const { return this->data; } + /*=======================================================================*/ + inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) ); + #endif + + return indexer.getIndex(x1,x2,x3,nx1,nx2,nx3); + } + + + /*=======================================================================*/ + //success -> true + //else -> false + inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3) const + { + if( x1 < 0 || x1 >= this->nx1 + || x2 < 0 || x2 >= this->nx2 + || x3 < 0 || x3 >= this->nx3 ) + { + return false; + } + return true; + } +protected: + /*=======================================================================*/ + std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3) const + { + std::stringstream out("index out of range - "); + out<<"("<<x1<<","<<x2<<","<<x3<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<")"; + return out.str(); + } + /*=======================================================================*/ + +protected: + size_type nx1; + size_type nx2; + size_type nx3; + indexer_type indexer; + std::vector< value_type > data; + +}; + +#endif //CBARRAY3D_H diff --git a/VirtualFluidsBasics/basics/container/CbArray4D.h b/VirtualFluidsBasics/basics/container/CbArray4D.h new file mode 100644 index 0000000000000000000000000000000000000000..b72a13f0e0489869e69ac722493ddc59e6c469e8 --- /dev/null +++ b/VirtualFluidsBasics/basics/container/CbArray4D.h @@ -0,0 +1,451 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CbArray4D.h +//! \ingroup container +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef CBARRAY4D_H +#define CBARRAY4D_H + + + +#include <iomanip> +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbEqual.h> +#include <algorithm> +#include <typeinfo> +#include "PointerDefinitions.h" + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// IndexClasses + +//IndexerX1X2X3X4: +//x4-reihen "liegen am stueck" im speicher +//optimaler schleifendurchlauf +//for(alle X1) +// for(alle X2) +// for(alle X3) +// for(alle X4) +class IndexerX1X2X3X4 +{ +public: + typedef int size_type; +public: + inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4 + , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 ) const + { + return nx4*(nx3*(nx2*x1+ x2)+x3)+x4 ; + } + inline std::size_t getStartIndexOfSortedArray( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4 + , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 ) const + { + return nx4*(nx3*(nx2*x1+ x2)+x3); + } +}; +////////////////////////////////////////////////////////////////////////// +// IndexClasses + +//IndexerX4X3X2X1: +//x1-reihen "liegen am stueck" im speicher +//optimaler schleifendurchlauf +//for(alle X4) +// for(alle X3) +// for(alle X2) +// for(alle X1) +class IndexerX4X3X2X1 +{ +public: + typedef size_t size_type; +public: + inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4 + , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 ) const + { + return nx1*(nx2*(nx3*x4+ x3)+x2)+x1; + } + inline std::size_t getStartIndexOfSortedArray( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4 + , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 ) const + { + return nx1*(nx2*(nx3*x4+ x3)+x2); + } +}; +////////////////////////////////////////////////////////////////////////// +// CbArray4D +//! \brief 4D Array +//! \details The data is stored in a vector +//! +//! Rangecheck active, if: +//! +//! -debug : not defined "NO_CB_RANGECHECK" +//! +//! -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK" +////////////////////////////////////////////////////////////////////////// +template<typename T, typename IndexClass = IndexerX4X3X2X1> +class CbArray4D +{ +public: + typedef SPtr< CbArray4D <T,IndexClass> > CbArray4DPtr; + + typedef T value_type; + typedef IndexClass indexer_type; + typedef typename IndexClass::size_type size_type; + typedef typename std::vector< value_type >::reference reference; + typedef typename std::vector< value_type >::const_reference const_reference; + typedef typename std::vector< value_type >::pointer pointer; + typedef typename std::vector< value_type >::const_pointer const_pointer; + +private: + template< typename value_type2, typename IndexClass2 > friend class CbArray4D; + +public: + /*=======================================================================*/ + CbArray4D() + { + this->resize(0,0,0,0); + } + /*=======================================================================*/ + CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4) + { + this->resize(nx1,nx2,nx3,nx4); + } + /*=======================================================================*/ + CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val) + { + this->resize(nx1,nx2,nx3,nx4,val); + } + /*=======================================================================*/ + CbArray4D(const size_type& uniformDimensionSize /*nx1=nx2=nx3=nx4*/) + { + this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); + } + /*=======================================================================*/ + //ubernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird) + CbArray4D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4) + { + assert( (nx1*nx2*nx3*nx4)==vec.size() ); + this->data.swap(vec); + this->resize(nx1,nx2,nx3,nx4); + } + /*=======================================================================*/ + CbArray4D(const CbArray4D& src) + : nx1(src.nx1) + , nx2(src.nx2) + , nx3(src.nx3) + , nx4(src.nx4) + , data(src.data) + { + } + /*=======================================================================*/ + template< typename value_type2 > + CbArray4D(const CbArray4D< value_type2 >& src) + : nx1(src.nx1) + , nx2(src.nx2) + , nx3(src.nx3) + , nx4(src.nx4) + { + //Sourcedaten kopieren + this->data.resize( src.data.size() ); + for(std::size_t i=0; i<data.size(); ++i) + this->data[i] = src.data[i]; + } + /*=======================================================================*/ + virtual ~CbArray4D() + { + //vector wird automatisch zerstoert + } + /*=======================================================================*/ + CbArray4D& operator= (const CbArray4D& rhs) + { + if(this == &rhs) return *this; + + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + this->nx3 = rhs.nx3; + this->nx4 = rhs.nx4; + + //gespeicherte Datenelemente loeschen + //Laenge anpassen + this->data.resize(rhs.data.size()); + //gespeicherte Datenelemente loeschen + this->data.clear(); + + //Sourcedaten kopieren + this->data = rhs.data; + + return *this; + } + /*=======================================================================*/ + //durch value_type2 kann man z.B. ein float Array einem double Array zuweisen! + template< typename value_type2, typename IndexClass2 > + CbArray4D& operator= (const CbArray4D< value_type2, IndexClass2 >& rhs) + { + this->nx1 = rhs.nx1; + this->nx2 = rhs.nx2; + this->nx3 = rhs.nx3; + this->nx4 = rhs.nx4; + + //gespeicherte Datenelemente loeschen + this->data.clear(); + //Laenge anpassen + this->data.resize(rhs.data.size()); + + //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + for(int x1=0; x1<this->nx1; x1++) + for(int x2=0; x2<this->nx2; x2++) + for(int x3=0; x3<this->nx3; x3++) + for(int x4=0; x4<this->nx4; x4++) + this->operator()(x1,x2,x3,x4) = static_cast< value_type >( rhs.operator()(x1,x2,x3,x4)); + + return *this; + } + /*=======================================================================*/ + bool operator== (const CbArray4D& rhs) const + { + if( this == &rhs ) return true; + + if( this->nx1!=rhs.nx1 + || this->nx2!=rhs.nx2 + || this->nx3!=rhs.nx3 + || this->nx4!=rhs.nx4 + || this->data.size() != rhs.data.size() ) + { + return false; + } + + return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() ); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator== (const CbArray4D< value_type2, IndexClass2 >& rhs) const + { + if( this->data.size() != rhs.data.size() ) return false; + + //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen) + for(int x4=0; x4<this->nx4; x4++) + for(int x3=0; x3<this->nx3; x3++) + for(int x2=0; x2<this->nx2; x2++) + for(int x1=0; x1<this->nx1; x1++) + if( !isUbEqual(this->operator()(x1,x2,x3,x4), rhs.operator()(x1,x2,x3,x4)) ) + return false; + + return true; + } + /*=======================================================================*/ + bool operator!= (const CbArray4D& rhs) const + { + return !(*this==rhs); + } + /*=======================================================================*/ + template< typename value_type2, typename IndexClass2 > + bool operator!= (const CbArray4D< value_type2, IndexClass2 >& rhs) const + { + return !(*this==rhs); + } + /*=======================================================================*/ + reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)]; + } + /*=======================================================================*/ + const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + #ifdef CbArray4D_RANGECHECKING + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)]; + } + /*=======================================================================*/ + pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)]; + } + /*=======================================================================*/ + const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)]; + } + /*=======================================================================*/ + void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4, const value_type& value) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)] = value; + } + /*=======================================================================*/ + reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)]; + } + /*=======================================================================*/ + const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + return (*this)(x1,x2,x3,x4,nx1,nx2,nx3,nx4); + } + /*=======================================================================*/ + bool isEmpty() const { return data.empty(); } + size_type getNX1() const { return this->nx1; } + size_type getNX2() const { return this->nx2; } + size_type getNX3() const { return this->nx3; } + size_type getNX4() const { return this->nx4; } + /*=======================================================================*/ + void reset(const value_type& val) + { + std::fill( this->data.begin(), this->data.end(), val ); + } + /*=======================================================================*/ + std::string toString() const + { + std::stringstream text; + text<<std::setprecision(19); + for(size_type x1=0; x1<this->nx1; x1++) + { + for(size_type x2=0; x2<this->nx2; x2++) + { + for(size_type x3=0; x3<this->nx3; x3++) + { + for(size_type x4=0; x4<this->nx4; x4++) + { + text<<(*this)(x1,x2,x3,x4)<<", "; + } + text<<std::endl; + } + text<<std::endl; + } + text<<std::endl<<std::endl; + } + + return text.str(); + } + /*=======================================================================*/ + std::string getInfo() const + { + std::stringstream text; + text<<"CbArray4D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >"; + text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<", nx4="<<this->nx4<<")"; + return text.str(); + } + /*=======================================================================*/ + void resize(const size_type& uniformDimensionSize) { this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); } + /*=======================================================================*/ + void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->nx3 = nx3; + this->nx4 = nx4; + this->data.resize(nx1*nx2*nx3*nx4); + } + /*=======================================================================*/ + void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val) + { + this->nx1 = nx1; + this->nx2 = nx2; + this->nx3 = nx3; + this->nx4 = nx4; + this->data.resize(nx1*nx2*nx3*nx4,val); + } + /*=======================================================================*/ + std::vector< value_type >& getDataVector() { return this->data; } + /*=======================================================================*/ + const std::vector< value_type >& getDataVector() const { return this->data; } + /*=======================================================================*/ + inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if( !this->indicesInRange(x1,x2,x3,x4) ) + UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) ); + #endif + + return indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4); + } + +protected: + /*=======================================================================*/ + //success -> true + //else -> false + inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + if( x1 < 0 || x1 >= this->nx1 + || x2 < 0 || x2 >= this->nx2 + || x3 < 0 || x3 >= this->nx3 + || x4 < 0 || x4 >= this->nx4 ) + { + return false; + } + return true; + } + /*=======================================================================*/ + std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const + { + std::stringstream out("index out of range - "); + out<<"("<<x1<<","<<x2<<","<<x3<<","<<x4<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<","<<nx4<<")"; + return out.str(); + } + /*=======================================================================*/ + +protected: + size_type nx1; + size_type nx2; + size_type nx3; + size_type nx4; + indexer_type indexer; + std::vector< value_type > data; + +}; + +#endif //CBARRAY4D_H diff --git a/VirtualFluidsBasics/basics/container/CbVector.h b/VirtualFluidsBasics/basics/container/CbVector.h new file mode 100644 index 0000000000000000000000000000000000000000..b33ad1a44ea4afa13107326fd68cd0f08adfe10b --- /dev/null +++ b/VirtualFluidsBasics/basics/container/CbVector.h @@ -0,0 +1,307 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CbVector.h +//! \ingroup container +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef CBVECTOR_H +#define CBVECTOR_H + +#include <vector> +#include <algorithm> //for std::swap +#include <typeinfo> //for typeid +#include <PointerDefinitions.h> //for memcopy + +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbEqual.h> + +template< typename T > class CbVectorAllocator; +template< typename T > class CbVectorAllocatorStd; + +//========================================================================= +//! \brief A class implements a container like a vector +//! \details +//! For this class it was required to ave only the type as template argument. +//! Hence, the allocator must be an abstract class. With out this requirement, +//! an allocator as second template argument would have been possible, as in the +//! STL vector. This would lead to the compiler generating two different classes +//! for the same data type with different allocators during compile time. Here it +//! is required that the same class can have different allocators. +//! +//! Rangecheck active, if: +//! -debug : not defined "NO_CB_RANGECHECK" +//! -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK" +//========================================================================= +////////////////////////////////////////////////////////////////////////// +template< typename T > +class CbVector +{ +public: + typedef T value_type; + typedef value_type* pointer; + typedef std::size_t size_type; + + friend class CbVectorAllocator<value_type>; //um auf ptrData und dataSize zugreifen zu koennen! + +public: + /*==========================================================*/ + CbVector( CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type> ) + : ptrData(NULL) + , dataSize(0) + , allocator(allocator) + { + this->allocator->alloc(*this,0,value_type()); + } + /*==========================================================*/ + CbVector( const size_type size, CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type>, const value_type& value=value_type() ) + : ptrData(NULL) + , dataSize(0) + , allocator(allocator) + { + this->allocator->alloc(*this,size,value); + } + /*==========================================================*/ + virtual ~CbVector() + { + if(allocator) + { + this->allocator->dealloc(*this); + delete allocator; + allocator=NULL; + } + } + /*=======================================================================*/ + CbVector& operator= (const CbVector& src) + { + if(this == &src) return *this; + + //gespeicherte Datenelemente loeschen + //Laenge anpassen + this->allocator->resize(*this, src.size()); + + //gespeicherte Datenelemente kopieren + if( !src.empty() ) + { + memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); + //for(size_type i=0; i<src.size(); i++) + // (*this)[i] = src[i]; + } + + return *this; + } + /*=======================================================================*/ + CbVector& operator= (const std::vector< value_type >& src) + { + //gespeicherte Datenelemente loeschen + //Laenge anpassen + this->allocator->resize(*this, src.size()); + + //gespeicherte Datenelemente kopieren + if( !src.empty() ) + { + memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); + //for(size_type i=0; i<src.size(); i++) + // (*this)[i] = src[i]; + } + + return *this; + } + /*=======================================================================*/ + bool operator== (const CbVector& rhs) const + { + if( this == &rhs ) return true; + if( this->dataSize != rhs.dataSize ) return false; + + for(size_type i=0; i<rhs.size(); i++) + if( !isUbEqual( this->operator[](i), rhs.operator[](i) ) ) + return false; + + return true; + } + /*==========================================================*/ + void setAllocator( CbVectorAllocator<value_type>* const& allocator ) + { + if(this->allocator) + { + if(this->allocator==allocator) return; + this->allocator->dealloc(*this); + delete this->allocator; + } + this->allocator = allocator; + this->allocator->alloc(*this,0); + } + /*==========================================================*/ + size_type size() const { return dataSize; } + /*==========================================================*/ + bool empty() const { return dataSize==0; } + /*==========================================================*/ + bool resize(const size_type& dataSize) + { + return allocator->resize(*this, dataSize); + } + /*==========================================================*/ + bool resize(const size_type& dataSize, const value_type& value) + { + return allocator->resize(*this, dataSize, value); + } + /*==========================================================*/ + void swap(CbVector& rhs) + { + if( this == &rhs ) return; + + std::swap( this->ptrData , rhs.ptrData ); + std::swap( this->dataSize , rhs.dataSize ); + std::swap( this->allocator, rhs.allocator ); + } + /*==========================================================*/ + value_type& operator[](const size_type& i) + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if(i>=dataSize) + UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") ); + #endif // _DEBUG + + return ptrData[i]; + } + /*==========================================================*/ + const value_type& operator[](const size_type& i) const + { + #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) ) + if(i>=dataSize) + UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") ); + #endif // _DEBUG + + return ptrData[i]; + } + /*==========================================================*/ + CbVectorAllocator<value_type>* getAllocator() const { return allocator; } + /*==========================================================*/ + +private: + value_type* ptrData; + size_type dataSize; + CbVectorAllocator<value_type>* allocator; + CbVector<value_type>(const CbVector<value_type>& src); + //CbVector<value_type>& operator=(const CbVector<value_type>& src); +}; + +////////////////////////////////////////////////////////////////////////// +// CbVectorAllocator-Interface +////////////////////////////////////////////////////////////////////////// +template< typename T > +class CbVectorAllocator +{ +public: + typedef typename CbVector<T>::value_type value_type; + typedef typename CbVector<value_type>::size_type size_type; + +public: + CbVectorAllocator() {} + virtual ~CbVectorAllocator() {} + + virtual bool alloc(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0; + virtual bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0; + virtual bool dealloc(CbVector< value_type >& vec) = 0; + +protected: + //folgende Methoden ersparen eine friend Deklaierung aller moeglichen Allocatoren + //denn durch diese beiden Methoden haben sie exklusive Zugriffsrechte! + //**********************************************************************************// + inline value_type*& ptrDataOf( CbVector< value_type >& vec ) + { + if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") ); + return vec.ptrData; + } + //**********************************************************************************// + inline size_type& dataSizeOf( CbVector< value_type >& vec ) + { + if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") ); + return vec.dataSize; + } +}; + +////////////////////////////////////////////////////////////////////////// +// CbVectorAllocatorStd +////////////////////////////////////////////////////////////////////////// +template< typename T > +class CbVectorAllocatorStd : public CbVectorAllocator<T> +{ +public: + //typedefs wiederholen, da Basisklasse = template -> "Dependent-Base"-Problem + typedef typename CbVector<T>::value_type value_type; + typedef typename CbVector<value_type>::size_type size_type; + +public: + CbVectorAllocatorStd() : CbVectorAllocator<value_type>() + { + + } + /*==========================================================*/ + bool alloc(CbVector< value_type >& src, const size_type& dataSize, const value_type& value=value_type()) + { + return this->resize(src,dataSize,value); + } + /*==========================================================*/ + bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) + { + if( CbVectorAllocatorStd< value_type >::dataSizeOf(vec) == dataSize) return false; + + //new array + value_type* new_data = new value_type[dataSize]; + //copy existing data to array + if( this->ptrDataOf(vec) ) + { + for(size_type i=0; (i<vec.size() && i<dataSize); ++i) new_data[i] = CbVectorAllocatorStd< value_type >::ptrDataOf(vec)[i]; + delete[] this->ptrDataOf(vec); + } + this->ptrDataOf(vec) = new_data; + //new value for new items + for(size_type i=this->dataSizeOf(vec); i<dataSize; ++i) this->ptrDataOf(vec)[i] = value; + //assign new dataSize + this->dataSizeOf(vec) = dataSize; + + return true; + } + /*==========================================================*/ + bool dealloc(CbVector< value_type >& vec) + { + if( this->ptrDataOf(vec) ) + { + delete[] this->ptrDataOf(vec); + this->ptrDataOf(vec) = NULL; + } + this->dataSizeOf(vec) = 0; + return true; + } + /*==========================================================*/ + +private: +}; + +#endif //CBVECTOR_H diff --git a/VirtualFluidsBasics/basics/objects/CMakePackage.txt b/VirtualFluidsBasics/basics/objects/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsBasics/basics/objects/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsBasics/basics/objects/ObObject.h b/VirtualFluidsBasics/basics/objects/ObObject.h new file mode 100644 index 0000000000000000000000000000000000000000..3fee350654bbdac50e31d70414c2f3bd9cfbe1a6 --- /dev/null +++ b/VirtualFluidsBasics/basics/objects/ObObject.h @@ -0,0 +1,61 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file ObObject.h +//! \ingroup objects +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef OBOBJECT_H +#define OBOBJECT_H + +#include <string> + +#include <basics/utilities/UbObservable.h> + +class ObObject : public UbObservable +{ +public: + ObObject() : name("") { } + ObObject(const std::string& name) : name(name) { } + + virtual ~ObObject() { } + + virtual ObObject* clone()=0; + + virtual std::string getName() { return name; } + void setName(std::string name) { this->name=name; } + + virtual std::string toString()=0; + + +private: + std::string name; +}; + + +#endif diff --git a/VirtualFluidsBasics/basics/utilities/CMakePackage.txt b/VirtualFluidsBasics/basics/utilities/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..0127c6fb70ba58900bfa7e273ffb1e02ece1c37e --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/CMakePackage.txt @@ -0,0 +1,21 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption) + +IF(${outOption}) + IF(WIN32) + ADD_DEFINITIONS( -DNOMINMAX ) + ENDIF(WIN32) + + IF(BOOST_VERSION) + OPTION(USE_THREADSAFE_LOGGER "ON=thread safe, OFF=not thread safe" ON) + IF(NOT ${outOption}) + ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING) + ELSE() + SET(NECESSARY_BOOST_LIBS ${NECESSARY_BOOST_LIBS} thread) + ENDIF() + ELSE() + #um die thread safe zu machen benoetigt man boost + ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING) + ENDIF() + +ENDIF() \ No newline at end of file diff --git a/VirtualFluidsBasics/basics/utilities/UbComparators.h b/VirtualFluidsBasics/basics/utilities/UbComparators.h new file mode 100644 index 0000000000000000000000000000000000000000..11f85e18b1cd63b0a5b0eb1f75e07d9fdb6e7aa6 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbComparators.h @@ -0,0 +1,231 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbComparators.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBCOMPARATORS_H +#define UBCOMPARATORS_H + +#include <functional> + +namespace UbComparators +{ + //type_traits + template <typename T> struct MemberInfo; //not defined for correct compiler errors! + + // specialization for MemberFunctionsPtr + // C - class with return T method + template <typename T, typename C> + struct MemberInfo<T C::*> + { + typedef T type; + typedef C class_type; + + static T& apply( C& c, T C::* ptr ) { return c.*ptr; } + static const T& apply( const C& c, T C::* ptr ) { return c.*ptr; } + }; + //specialization for MemberFunctionsPtr + //C - class with return T method + template <typename T, typename C> + struct MemberInfo<T (C::*)()> + { + typedef T type; + typedef C class_type; + + static T apply( C& c, T (C::*ptr)() ) { return (c.*ptr)(); } + }; + //specialization for const MemberFunctionsPtr + //C - class with return T method + template <typename T, typename C> + struct MemberInfo<T (C::*)() const> + { + typedef T type; + typedef C class_type; + + static T apply( const C& c, T (C::*ptr)() const ) { return (c.*ptr)(); } + }; + + //MemberComparative-Class + template <typename Ptr, typename Comp = std::less<typename MemberInfo<Ptr>::type> > + class MemComp + : private Comp // -> usage of Empty Base Class Optimization (EBCO) + { + typedef typename MemberInfo<Ptr>::class_type C; + + public: + MemComp( Ptr ptr, Comp c = Comp() ) + : Comp(c), mp_(ptr) + {} + + bool operator()(C& lhs, C& rhs) + { + return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); + } + bool operator()(C& lhs, C& rhs) const + { + return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); + } + bool operator()(const C& lhs, const C& rhs) + { + return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); + } + bool operator()(const C& lhs, const C& rhs) const + { + return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); + } + + private: + Ptr mp_; + }; + + // Factoryfunktionen + template <typename Ptr> + MemComp<Ptr> membercomp(Ptr p) + { + return MemComp<Ptr>(p); + } + + template<typename Comp, typename Ptr> + MemComp<Ptr, Comp> membercomp(Ptr p, Comp c = Comp()) + { + return MemComp<Ptr, Comp>(p, c); + } + + template<template<typename> class Comp, typename Ptr> + MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> > + membercomp(Ptr p, Comp<typename MemberInfo<Ptr>::type> c = Comp<typename MemberInfo<Ptr>::type>()) + { + return MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> >(p, c); + } + + + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + //andere Variante (alerdings ist hier keine Deduction moeglich!!!) + ////////////////////////////////////////////////////////////////////////// + //Vergleichs-Templates: + //Funktor zum "non-const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1 ); + template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() /*MethodenPointer*/> // Allgemeiner Fall + struct compareMethods + { + bool operator()(K& r, K& l) const // da fct nicht const ist, kann auch K nicht const sein. das const hinter der deklaration besagt dass compareMethods const sein kann + { return (r.*fct)() < (l.*fct)(); } + }; + ////////////////////////////////////////////////////////////////////////// + //Funktor zum "const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1 ); + template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() const /*MethodenPointer*/> // <- hier const + struct compareConstMethods + { + bool operator()(const K& r, const K& l) const //hier koennen die K's auch const sein, muessen sie aber nicht (const hinzufuegen geht ja problemlos) + { return (r.*fct)() < (l.*fct)(); } + }; + ////////////////////////////////////////////////////////////////////////// + //Funktor zum Membervergleich: lise.sort( compareMember<Klasse, int, &Klasse::member>() ); + template<typename K/*Klasse*/, typename M /*MemberTyp*/, M (K::*Member) /*MemberPointer*/> // <- hier const + struct compareMember + { + bool operator()(const K& r,const K& l) const + { return r.*Member < l.*Member; } + }; + //Bsp: + //class Klasse{ + //public: + // Klasse(double val1, double val2 ) : val1(val1),val2(val2) {} + // double getVal1() { return val1; } + // double getVal2() const { return val2; } // <- hier const + // double val1, val2; + //}; + //int main(int argc, char** argv){ + // std::list<Klasse> l; + // l.push_back( Klasse(10,10) ); + // l.push_back( Klasse(1,5) ); + // l.sort( compareMember<Klasse, double, &Klasse::val1 >() ); + // l.sort( compareMethods<Klasse, double, &Klasse::getVal1 >() ); + // l.sort( compareConstMethods<Klasse, double, &Klasse::getVal1 >() ); + //} + +}; + +#endif //UBCOMPARATOR_H + +//example +// #include <basics/utilities/UbComparators.h" +// #include <list> +// using namespace std; +// using namespace UbComparators; +// +// struct S { +// S(int i) :x(i) {} +// int x; +// float f() {return x;}; +// double g() const {return x;} +// }; +// +// struct intComp { +// bool operator()(int l, int r) const +// { return l > r; } +// }; +// +// struct dblComp { +// bool operator()(double l, double r) const +// { return l > r; } +// }; +// +// template <typename T> +// struct genComp { +// bool operator()(const T& l, const T& r) const +// { return l > r; } +// }; +// +// +// int main() +// { +// S a(1); +// S b(2); +// list<S> sList; +// sList.push_back(a); +// sList.push_back(b); +// sList.sort(UbComparators::membercomp(&S::x,intComp())); //calls overload (1) +// sList.sort(UbComparators::membercomp<intComp>(&S::x)); //same +// sList.sort(UbComparators::membercomp(&S::x)); //calls overload (5) +// sList.sort(UbComparators::membercomp<genComp>(&S::x)); //calls overload(3) +// sList.sort(UbComparators::membercomp(&S::x, genComp<int>())); //calls overload(1) +// //same for nonconst function +// sList.sort(UbComparators::membercomp(&S::f, dblComp())); //overload(2) +// sList.sort(UbComparators::membercomp<dblComp>(&S::f)); //same +// sList.sort(UbComparators::membercomp(&S::f)); //overload(6) +// sList.sort(UbComparators::membercomp<genComp>(&S::f)); //overload(4) +// //same for const function +// sList.sort(UbComparators::membercomp(&S::g, dblComp())); //overload(2) +// sList.sort(UbComparators::membercomp<dblComp>(&S::g)); //same +// sList.sort(UbComparators::membercomp(&S::g)); //overload(6) +// sList.sort(UbComparators::membercomp<genComp>(&S::g)); //overload(4) +// } diff --git a/VirtualFluidsBasics/basics/utilities/UbEqual.h b/VirtualFluidsBasics/basics/utilities/UbEqual.h new file mode 100644 index 0000000000000000000000000000000000000000..483e50a799c3afd1eab055bba3f243413774472c --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbEqual.h @@ -0,0 +1,145 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbEqual.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBEQUAL_H +#define UBEQUAL_H + +#include<cmath> + +////////////////////////////////////////////////////////////////////////// +// +//! \brief isUbEqual<T1,T2>(a,b) +//! Compares the equality of values a and b. +//! +//! By default operator== is used for this. +//! +//! Execption: floating-point variables +//! In these cases the type with higher precision is casted to the type of lower precision +//! and then the two values are compared. +//! e.g.: double d=1.2; int i=1; bool check = isUbEqual(d,i); -> true +//! +//! For classes operator== must be implemented for const objects! +//! e.g.: bool operator==(const Test&) const { if(blabla) return true; else return false; } +// +////////////////////////////////////////////////////////////////////////// + +//std-trait, fuer alle nicht spezifischen typen: +template < typename T1, typename T2 > +struct UbEqualTrait +{ + typedef T1 High; + typedef T1 Low; +}; + +//std-trait, fuer gleiche T +template < typename T > +struct UbEqualTrait< T, T > +{ + typedef T High; + typedef T Low; +}; + +//spezialisierung für diverse Typen-Tuples +template<> struct UbEqualTrait< short, int > { typedef int High; typedef short Low; }; +template<> struct UbEqualTrait< short, long > { typedef long High; typedef short Low; }; +template<> struct UbEqualTrait< short, float > { typedef float High; typedef short Low; }; +template<> struct UbEqualTrait< short, double > { typedef double High; typedef short Low; }; +template<> struct UbEqualTrait< short, long double > { typedef long double High; typedef short Low; }; + +template<> struct UbEqualTrait< int, short > { typedef int High; typedef short Low; }; +template<> struct UbEqualTrait< int, long > { typedef long High; typedef int Low; }; +template<> struct UbEqualTrait< int, float > { typedef float High; typedef int Low; }; +template<> struct UbEqualTrait< int, double > { typedef double High; typedef int Low; }; +template<> struct UbEqualTrait< int, long double > { typedef long double High; typedef int Low; }; + +template<> struct UbEqualTrait< long, short > { typedef long High; typedef short Low; }; +template<> struct UbEqualTrait< long, int > { typedef long High; typedef int Low; }; +template<> struct UbEqualTrait< long, float > { typedef float High; typedef long Low; }; +template<> struct UbEqualTrait< long, double > { typedef double High; typedef long Low; }; +template<> struct UbEqualTrait< long, long double > { typedef long double High; typedef long Low; }; + +template<> struct UbEqualTrait< float, short > { typedef float High; typedef short Low; }; +template<> struct UbEqualTrait< float, int > { typedef float High; typedef int Low; }; +template<> struct UbEqualTrait< float, long > { typedef float High; typedef long Low; }; +template<> struct UbEqualTrait< float, double > { typedef double High; typedef float Low; }; +template<> struct UbEqualTrait< float, long double > { typedef long double High; typedef float Low; }; + +template<> struct UbEqualTrait< double, short > { typedef double High; typedef short Low; }; +template<> struct UbEqualTrait< double, int > { typedef double High; typedef int Low; }; +template<> struct UbEqualTrait< double, long > { typedef double High; typedef long Low; }; +template<> struct UbEqualTrait< double, float > { typedef double High; typedef float Low; }; +template<> struct UbEqualTrait< double, long double > { typedef long double High; typedef double Low; }; + +template<> struct UbEqualTrait< long double, short > { typedef long double High; typedef short Low; }; +template<> struct UbEqualTrait< long double, int > { typedef long double High; typedef int Low; }; +template<> struct UbEqualTrait< long double, long > { typedef long double High; typedef long Low; }; +template<> struct UbEqualTrait< long double, float > { typedef long double High; typedef float Low; }; +template<> struct UbEqualTrait< long double, double > { typedef long double High; typedef double Low; }; + +////////////////////////////////////////////////////////////////////////// +//fuer Allgmeine-Typen ( operator== ): +template< typename T1, typename T2 > +inline bool specific_equal(const T1& a, const T2& b) { return a==b; } + +////////////////////////////////////////////////////////////////////////// +//fuer floating point build-in-type +//float.float +template< /*float,float*/> +inline bool specific_equal< float, float >(const float& a, const float& b) { return std::fabs( a - b ) < 1E-8; } + +template</*double,double*/> +inline bool specific_equal< double, double >(const double& a, const double& b) { return std::fabs( a - b ) < 1E-13; } + +template</*long double,long double*/> +inline bool specific_equal< long double, long double >(const long double& a, const long double& b) { return std::fabs( a - b ) < 1E-16; } + +////////////////////////////////////////////////////////////////////////// +//globale isUbEqual - Funktion +template< typename T1, typename T2 > +inline bool isUbEqual(const T1& a, const T2& b) +{ + typedef typename UbEqualTrait<T1,T2>::Low Low; + return specific_equal< Low, Low >(static_cast< Low >( a ),static_cast< Low >( b )); +}; + +////////////////////////////////////////////////////////////////////////// +//UbEqual-Functor +template< typename T1, typename T2 > +struct UbEqual +{ + bool operator()(const T1& a, const T2& b) + { + return isUbEqual(a,b); + } +}; + +#endif //UBEQUAL_H diff --git a/VirtualFluidsBasics/basics/utilities/UbException.h b/VirtualFluidsBasics/basics/utilities/UbException.h new file mode 100644 index 0000000000000000000000000000000000000000..cb8550c1e0523683440d13fff879111cf09c924f --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbException.h @@ -0,0 +1,177 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbException.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBEXCEPTION_H +#define UBEXCEPTION_H + +#include <vector> +#include <iostream> +#include <string> +#include <sstream> +#include <stdexcept> + +#include "./UbTuple.h" + +//========================================================================= +// +//! \brief UbException +//! usage: UB_THROW( UbException("error message") ); +//! UB_THROW( UbException(__FILE__, __LINE__,"error message") ); +//! UB_THROW( UbException(__FILE__, __LINE__,UB_FUNCTION,"error message") ); +//! UB_THROW( UbException(UB_EXARGS,"error") ); //same as above +// +//========================================================================= + +//Macro UB_FUNCTION: figures out the method/function name (platform dependant) +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) + # define UB_FUNCTION __PRETTY_FUNCTION__ +#elif defined(__DMC__) && (__DMC__ >= 0x810) + # define UB_FUNCTION __PRETTY_FUNCTION__ +#elif defined(__FUNCSIG__) + # define UB_FUNCTION __FUNCSIG__ +#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500)) + # define UB_FUNCTION __FUNCTION__ +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) + # define UB_FUNCTION __FUNC__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + # define UB_FUNCTION __func__ +#else + # define UB_FUNCTION "(unknown)" +#endif + +//Helper Marco +#define UB_EXARGS __FILE__,__LINE__,UB_FUNCTION + +#ifdef CAB_BOOST + #define UB_THROW(e) throw boost::enable_current_exception(e) +#else + #define UB_THROW(e) throw e +#endif + +class UbException : public std::runtime_error +{ +public: + typedef UbTuple< std::string, int, std::string, std::string > ExceptionData; +public: + ////////////////////////////////////////////////////////////////////////// + //constructors + UbException() + : std::runtime_error("") + { + } + /*==========================================================*/ + UbException(const std::string& str) + : std::runtime_error("") + { + this->addInfo(str); + } + /*==========================================================*/ + UbException(const std::string& file, const int& line, const std::string& err_str) + : std::runtime_error("") + { + this->addInfo(file,line,"unknown",err_str); + } + /*==========================================================*/ + //UbException(const char* file, const int& line, const char* function, const std::string& err_str) + UbException(const std::string& file, const int& line, const std::string& function, const std::string& err_str) + : std::runtime_error("") + { + this->addInfo(file,line,function,err_str); + } + ////////////////////////////////////////////////////////////////////////// + //destructor + virtual ~UbException() throw() { } + ////////////////////////////////////////////////////////////////////////// + //virtual public methods + //returns exception-string + virtual const char* what() const throw() + { + exceptionString = this->toString(); + return exceptionString.c_str(); //ansonsten ist das Verhalten anschließend undefiniert! + } + /*==========================================================*/ + virtual void addInfo(const std::string& err_str) + { + exceptionData.push_back( makeUbTuple( (std::string)"-", 0, (std::string)"unknown", err_str) ); + } + /*==========================================================*/ + //add exception + virtual void addInfo(const std::string& file, const int& line, const std::string& function, const std::string& err_str) + { + exceptionData.push_back( makeUbTuple( file, line, function, err_str ) ); + } + /*==========================================================*/ + //returns exception-string with all calles exceptions + virtual const std::vector<std::string> getInfo() const + { + std::vector<std::string> tmp; + for(std::size_t i=0; i<exceptionData.size(); i++) + { + std::stringstream str; + str << val<1>( exceptionData[i] ) << ", " + << val<2>( exceptionData[i] ) << ", " + << val<3>( exceptionData[i] ) << ", " + << val<4>( exceptionData[i] ); + tmp.push_back( str.str()); + } + return tmp; + } + /*==========================================================*/ + //returns exception-string with all calles exceptions and detailes informations + virtual std::string toString() const + { + std::stringstream str("UbExeption"); + + for(std::size_t i=0; i<exceptionData.size(); i++) + str<<(std::string)"caller[" << i << "]\n" + <<" - file: "<< val<1>( exceptionData[i] )<<"\n" + <<" - line: "<< val<2>( exceptionData[i] )<<"\n" + <<" - function: "<< val<3>( exceptionData[i] )<<"\n" + <<" - what: "<< val<4>( exceptionData[i] )<< std::endl; + + return str.str(); + } + +protected: + ////////////////////////////////////////////////////////////////////////// + //protected member + std::vector< ExceptionData > exceptionData; + mutable std::string exceptionString; +}; + +//overlading operator << +inline std::ostream& operator<<(std::ostream& os, const UbException& e) +{ + return os<<e.toString(); +} + +#endif //UBEXCEPTION_H diff --git a/VirtualFluidsBasics/basics/utilities/UbInfinity.h b/VirtualFluidsBasics/basics/utilities/UbInfinity.h new file mode 100644 index 0000000000000000000000000000000000000000..eebaf14166552ccbe4a23a516d28d2594c87494f --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbInfinity.h @@ -0,0 +1,210 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbInfinity.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UB_INFINITY_H +#define UB_INFINITY_H +#include <limits> + +#include <basics/utilities/UbLimits.h> +#include <basics/utilities/UbSystem.h> + +////////////////////////////////////////////////////////////////////////// +//! +//! \brief UbNegInfinity +//! \details Note: The UbNegInfinity class cannot be instantiated on its own, but works +//! as a base class for the Infinity class. +//! +////////////////////////////////////////////////////////////////////////// + +class UbNegInfinity +{ + public: + //name Conversion operators + inline operator signed char() const { return UbLimits<signed char>::ninf(); } + inline operator char() const { return UbLimits<char>::ninf(); } + inline operator wchar_t() const { return UbLimits<wchar_t>::ninf(); } + inline operator short() const { return UbLimits<short>::ninf(); } + inline operator int() const { return UbLimits<int>::ninf(); } + inline operator long() const { return UbLimits<long>::ninf(); } + inline operator float() const { return UbLimits<float>::ninf(); } + inline operator double() const { return UbLimits<double>::ninf(); } + inline operator long double() const { return UbLimits<long double>::ninf(); } + + //! This function compares built-in data types with their largest possible value. The function + //! only works for built-in data types. The attempt to compare user-defined class types will + //! result in a compile time error. + template< typename T > + inline bool equal( const T& rhs ) const + { + UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized ); + return UbLimits<T>::ninf() == rhs; + } + protected: + inline UbNegInfinity() {} + + private: + UbNegInfinity( const UbNegInfinity& ninf ); //copy constructor (private & undefined) + UbNegInfinity& operator=( const UbNegInfinity& ninf ); //copy assignment operator (private & undefined) + void* operator&() const; //address operator (private & undefined) +}; + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= +template< typename T > +inline bool operator==( const UbNegInfinity& lhs, const T& rhs ) +{ + return lhs.equal( rhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator==( const T& lhs, const UbNegInfinity& rhs ) +{ + return rhs.equal( lhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator!=( const UbNegInfinity& lhs, const T& rhs ) +{ + return !lhs.equal( rhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator!=( const T& lhs, const UbNegInfinity& rhs ) +{ + return !rhs.equal( lhs ); +} + +////////////////////////////////////////////////////////////////////////// +// +// UbInfinity +// +////////////////////////////////////////////////////////////////////////// +class UbInfinity : public UbNegInfinity //um später -UbInfinity leichter zu implementieren!!! +{ + public: + inline UbInfinity() + : UbNegInfinity() + {} + + inline operator unsigned char() const { return UbLimits<unsigned char>::inf(); } + inline operator signed char() const { return UbLimits<signed char>::inf(); } + inline operator char() const { return UbLimits<char>::inf(); } + inline operator wchar_t() const { return UbLimits<wchar_t>::inf(); } + inline operator unsigned short() const { return UbLimits<unsigned short>::inf(); } + inline operator short() const { return UbLimits<short>::inf(); } + inline operator unsigned int() const { return UbLimits<unsigned int>::inf(); } + inline operator int() const { return UbLimits<int>::inf(); } + inline operator unsigned long() const { return UbLimits<unsigned long>::inf(); } + inline operator long() const { return UbLimits<long>::inf(); } + inline operator float() const { return UbLimits<float>::inf(); } + inline operator double() const { return UbLimits<double>::inf(); } + inline operator long double() const { return UbLimits<long double>::inf(); } + + inline const UbNegInfinity& operator-() const { return static_cast<const UbNegInfinity&>( *this ); } + + /*==========================================================*/ + template< typename T > + inline bool equal( const T& rhs ) const + { + UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized ); + return UbLimits<T>::inf() == rhs; + } + + private: + UbInfinity( const UbInfinity& inf ); //Copy constructor (private & undefined) + UbInfinity& operator=( const UbInfinity& inf ); //Copy assignment operator (private & undefined) + void* operator&() const; //Address operator (private & undefined) +}; + +////////////////////////////////////////////////////////////////////////// +// GLOBAL OPERATORS +////////////////////////////////////////////////////////////////////////// +template< typename T > +inline bool operator==( const UbInfinity& lhs, const T& rhs ); + +template< typename T > +inline bool operator==( const T& lhs, const UbInfinity& rhs ); + +template< typename T > +inline bool operator!=( const UbInfinity& lhs, const T& rhs ); + +template< typename T > +inline bool operator!=( const T& lhs, const UbInfinity& rhs ); +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Equality comparison between an Infinity object and a built-in data type. +// \ingroup util +// +// This operator works only for built-in data types. The attempt to compare user-defined class +// types will result in a compile time error. +*/ +template< typename T > +inline bool operator==( const UbInfinity& lhs, const T& rhs ) +{ + return lhs.equal( rhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator==( const T& lhs, const UbInfinity& rhs ) +{ + return rhs.equal( lhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator!=( const UbInfinity& lhs, const T& rhs ) +{ + return !lhs.equal( rhs ); +} +//************************************************************************************************* +template< typename T > +inline bool operator!=( const T& lhs, const UbInfinity& rhs ) +{ + return !rhs.equal( lhs ); +} +//************************************************************************************************* + +////////////////////////////////////////////////////////////////////////// +// GLOBAL INFINITY VALUE +////////////////////////////////////////////////////////////////////////// +namespace Ub +{ + //e.g. double x = UbSystem::inf; float x = -Ub::inf; + const UbInfinity inf; +} + +#endif //UB_INFINITY_H diff --git a/VirtualFluidsBasics/basics/utilities/UbKeys.h b/VirtualFluidsBasics/basics/utilities/UbKeys.h new file mode 100644 index 0000000000000000000000000000000000000000..1ee57815043ec3a36522e956435db0c78e276bd4 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbKeys.h @@ -0,0 +1,304 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbKeys.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBKEYS_H +#define UBKEYS_H + +#include <iostream> + + +#ifdef CAB_RCF + #include <3rdParty/rcf/RcfSerializationIncludes.h> +#endif //CAB_RCF + +////////////////////////////////////////////////////////////////////////// +//! +//! \brief +//! namespace for global Keys (e.g. for STL-maps) +//! +////////////////////////////////////////////////////////////////////////// + +namespace UbKeys +{ + //nested class + template< typename T1, typename T2 = T1 > + class Key2 + { + public: + ////////////////////////////////////////////////////////////////////////// + //Konstruktoren + Key2(const T1& t1, const T2& t2) + : t1(t1), t2(t2) + { + } + /*==========================================================*/ + Key2& operator=(const Key2& srcKey) + { + if(this == &srcKey ) return *this; + + t1 = srcKey.t1; + t2 = srcKey.t2; + + return *this; + } + /*==========================================================*/ + T1 getT1() const { return t1; } + T2 getT2() const { return t2; } + + ////////////////////////////////////////////////////////////////////////// + //global ueberladene Operatoren + friend inline bool operator<(const Key2& lhsKey,const Key2& rhsKey) + { + if( lhsKey.t1 < rhsKey.t1 ) return true; + if( lhsKey.t1 > rhsKey.t1 ) return false; + if( lhsKey.t2 < rhsKey.t2 ) return true; + + return false; + } + /*==========================================================*/ + friend inline bool operator==(const Key2& lhsKey, const Key2& rhsKey) + { + if(lhsKey.t1 != rhsKey.t1 ) return false; + if(lhsKey.t2 != rhsKey.t2 ) return false; + + return true; + } + //ueberladene Operatoren + friend inline bool operator!=(const Key2& lhsKey, const Key2& rhsKey) + { + return !(lhsKey == rhsKey); + } + //ueberladene Operatoren + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const Key2& key) + { + os<<"Key2<"<<typeid(T1).name()<<","<<typeid(T2).name()<<">,("<<key.t1<<","<<key.t2<<")"; + return os; + } + /*==========================================================*/ + #ifdef CAB_RCF + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & t1; + ar & t2; + } + #endif //CAB_RCF + + private: + ////////////////////////////////////////////////////////////////////////// + //private Member + T1 t1; + T2 t2; + + }; + + ////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////// + template< typename T1, typename T2 = T1, typename T3 = T1 > + class Key3 + { + public: + ////////////////////////////////////////////////////////////////////////// + //Konstruktoren + Key3() : t1(0), t2(0), t3(0) + { + + } + Key3(const T1& t1, const T2& t2, const T3& t3) + : t1(t1), t2(t2), t3(t3) + { + } + /*==========================================================*/ + T1 getT1() const { return t1; } + T2 getT2() const { return t2; } + T3 getT3() const { return t3; } + /*==========================================================*/ + Key3& operator=(const Key3& srcKey) + { + if(this == &srcKey ) return *this; + + t1 = srcKey.t1; + t2 = srcKey.t2; + t3 = srcKey.t3; + + return *this; + } + + ////////////////////////////////////////////////////////////////////////// + //global ueberladene Operatoren + friend inline bool operator<(const Key3& lhsKey,const Key3& rhsKey) + { + if( lhsKey.t1 < rhsKey.t1 ) return true; + if( lhsKey.t1 > rhsKey.t1 ) return false; + if( lhsKey.t2 < rhsKey.t2 ) return true; + if( lhsKey.t2 > rhsKey.t2 ) return false; + if( lhsKey.t3 < rhsKey.t3 ) return true; + + return false; + } + /*==========================================================*/ + friend inline bool operator==(const Key3& lhsKey,const Key3& rhsKey) + { + if(lhsKey.t1 != rhsKey.t1 ) return false; + if(lhsKey.t2 != rhsKey.t2 ) return false; + if(lhsKey.t3 != rhsKey.t3 ) return false; + + return true; + } + /*==========================================================*/ + //ueberladene Operatoren + friend inline bool operator!=(const Key3& lhsKey, const Key3& rhsKey) + { + return !(lhsKey == rhsKey); + } + + //ueberladene Operatoren + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const Key3& key) + { + os<<"Key3<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name(); + os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<")"; + return os; + } + /*==========================================================*/ + #ifdef CAB_RCF + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & t1; + ar & t2; + ar & t3; + } + #endif //CAB_RCF + + private: + ////////////////////////////////////////////////////////////////////////// + //private Member + T1 t1; + T2 t2; + T3 t3; + }; + + ////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////// + template< typename T1, typename T2 = T1, typename T3 = T1, typename T4 = T1 > + class Key4 + { + public: + ////////////////////////////////////////////////////////////////////////// + //Konstruktoren + Key4(const T1& t1, const T2& t2, const T3& t3, const T4& t4) + : t1(t1), t2(t2), t3(t3), t4(t4) + { + } + /*==========================================================*/ + T1 getT1() const { return t1; } + T2 getT2() const { return t2; } + T3 getT3() const { return t3; } + T4 getT4() const { return t4; } + /*==========================================================*/ + Key4& operator=(const Key4& srcKey) + { + if(this == &srcKey ) return *this; + + t1 = srcKey.t1; + t2 = srcKey.t2; + t3 = srcKey.t3; + t4 = srcKey.t4; + + return *this; + } + ////////////////////////////////////////////////////////////////////////// + //global ueberladene Operatoren + friend inline bool operator<(const Key4& lhsKey,const Key4& rhsKey) + { + if( lhsKey.t1 < rhsKey.t1 ) return true; + if( lhsKey.t1 > rhsKey.t1 ) return false; + if( lhsKey.t2 < rhsKey.t2 ) return true; + if( lhsKey.t2 > rhsKey.t2 ) return false; + if( lhsKey.t3 < rhsKey.t3 ) return true; + if( lhsKey.t3 > rhsKey.t3 ) return false; + if( lhsKey.t4 < rhsKey.t4 ) return true; + + return false; + } + /*==========================================================*/ + friend inline bool operator==(const Key4& lhsKey,const Key4& rhsKey) + { + if(lhsKey.t1 != rhsKey.t1 ) return false; + if(lhsKey.t2 != rhsKey.t2 ) return false; + if(lhsKey.t3 != rhsKey.t3 ) return false; + if(lhsKey.t4 != rhsKey.t4 ) return false; + + return true; + } + + //ueberladene Operatoren + friend inline bool operator!=(const Key4& lhsKey, const Key4& rhsKey) + { + return !(lhsKey == rhsKey); + } + //ueberladene Operatoren + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const Key4& key) + { + os<<"Key4<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name()<<","<<typeid(T4).name(); + os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<","<<key.t4<<")"; + return os; + } + /*==========================================================*/ + #ifdef CAB_RCF + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & t1; + ar & t2; + ar & t3; + ar & t4; + } + #endif //CAB_RCF + + private: + ////////////////////////////////////////////////////////////////////////// + //private Member + T1 t1; + T2 t2; + T3 t3; + T4 t4; + + }; +} + +#endif //UBKEYS_H diff --git a/VirtualFluidsBasics/basics/utilities/UbLimits.h b/VirtualFluidsBasics/basics/utilities/UbLimits.h new file mode 100644 index 0000000000000000000000000000000000000000..6a2aa9cdbdf4a290571bad4b96796cd5646f4fb3 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbLimits.h @@ -0,0 +1,165 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbLimits.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UB_LIMITS_H +#define UB_LIMITS_H + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include <limits> + +////////////////////////////////////////////////////////////////////////// +// CLASS DEFINITION +////////////////////////////////////////////////////////////////////////// +template< typename T > +struct UbLimits {}; + +////////////////////////////////////////////////////////////////////////// +// SPECIALIZATIONS +////////////////////////////////////////////////////////////////////////// +template<> +struct UbLimits<unsigned char> +{ + //return the largest possible positive unsigned char value + static inline unsigned char inf() { return std::numeric_limits<unsigned char>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<char> +{ + //return the largest possible positive char value. */ + static inline char inf () { return std::numeric_limits<char>::max(); } + //return the largest possible negative char value + static inline char ninf() { return std::numeric_limits<char>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<signed char> +{ + //return the largest possible positive signed char value + static inline signed char inf () { return std::numeric_limits<signed char>::max(); } + + //return The largest possible negative signed char value + static inline signed char ninf() { return std::numeric_limits<signed char>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<wchar_t> +{ + //return The largest possible positive wchar_t value + static inline wchar_t inf () { return std::numeric_limits<wchar_t>::max(); } + //return The largest possible negative wchar_t value + static inline wchar_t ninf() { return std::numeric_limits<wchar_t>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<unsigned short> +{ + //return The largest possible positive unsigned short value + static inline unsigned short inf() { return std::numeric_limits<unsigned short>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<short> +{ + //return The largest possible positive short value + static inline short inf () { return std::numeric_limits<short>::max(); } + //return The largest possible negative short value + static inline short ninf() { return std::numeric_limits<short>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<unsigned int> +{ + //return The largest possible positive unsigned int value + static inline unsigned int inf() { return std::numeric_limits<unsigned int>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<int> +{ + //return The largest possible positive int value + static inline int inf () { return std::numeric_limits<int>::max(); } + + //return The largest possible negative int value + static inline int ninf() { return std::numeric_limits<int>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<unsigned long> +{ + //return The largest possible positive unsigned long value + static inline unsigned long inf() { return std::numeric_limits<unsigned long>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<long> +{ + //return The largest possible positive long value + static inline long inf () { return std::numeric_limits<long>::max(); } + + //return The largest possible negative long value + static inline long ninf() { return std::numeric_limits<long>::min(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<float> +{ + //return The largest possible positive float value + static inline float inf () { return std::numeric_limits<float>::max(); } + + //return The largest possible negative float value + static inline float ninf() { return -std::numeric_limits<float>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<double> +{ + //return The largest possible positive double value + static inline double inf () { return std::numeric_limits<double>::max(); } + //return The largest possible negative double value + static inline double ninf() { return -std::numeric_limits<double>::max(); } +}; +//************************************************************************************************* +template<> +struct UbLimits<long double> +{ + //return The largest possible positive long double value + static inline long double inf () { return std::numeric_limits<long double>::max(); } + //return The largest possible negative long double value + static inline long double ninf() { return -std::numeric_limits<long double>::max(); } +}; + +#endif //UB_LIMITS_H diff --git a/VirtualFluidsBasics/basics/utilities/UbLogger.cpp b/VirtualFluidsBasics/basics/utilities/UbLogger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a02a1aa15c28410aadaa25466177f0db620383df --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbLogger.cpp @@ -0,0 +1,40 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbLogger.cpp +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <basics/utilities/UbLogger.h> + +#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING) + +boost::mutex Output2Stream::mtx; + +#endif // CAB_BOOST + diff --git a/VirtualFluidsBasics/basics/utilities/UbLogger.h b/VirtualFluidsBasics/basics/utilities/UbLogger.h new file mode 100644 index 0000000000000000000000000000000000000000..266ac1f6be415dfe05ca3796c1b4fbd6f2790fda --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbLogger.h @@ -0,0 +1,401 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbLogger.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBLOGGER_H +#define UBLOGGER_H + +#include <sstream> +#include <string> +#include <iostream> +#include <fstream> +#include <iomanip> + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__WIN64__) + #include <windows.h> +#else + #include <sys/time.h> +#endif + +#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING) + #include <boost/thread.hpp> +#endif // CAB_BOOST + + + +enum LogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logDEBUG5}; + +////////////////////////////////////////////////////////////////////////// +// template <typename OutputPolicy> class Log - declaration +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +//! +//! \brief +//! C++ Logger +//! \details Functionality: +//! Per logentry an object of type UbLogger is generated, the log string is passed to this object and +//! upon destruction of the object the string is written to a file or the screen depending on +//! the policy (=template paramter). Multiple log level are supported. +//! +//! helpermakro: UBLOG +//! +//! Example 1: +//! \code +//! UBLOG(logINFO) << "Klasse::foo entered"; //endl is not required +//! \endcode +//! +//! Example 2: +//! \code +//! try +//! { +//! UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG3"); +//! //UbLog::output_policy::setStream(&std::cerr); //<- clog is stdandard +//! UbLog::output_policy::setStream("c:/temp/out.txt"); //you can not open these -> error message -> log is output in cerr +//! +//! int count = 3; +//! UBLOG(logINFO, "A loop with " << count << " iterations"); +//! for (int i = 0; i != count; ++i) +//! { +//! UBLOG(logERROR , "error - the counter i = " << i ); +//! UBLOG(logDEBUG1, "debug1 - the counter i = " << i ); +//! UBLOG(logDEBUG2, "debug2 - the counter i = " << i ); +//! UBLOG(logDEBUG3, "debug3 - the counter i = " << i ); +//! //for MultiLine entries: -> formatting in logfile +//! UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +//! UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +//! UBLOG2ML(logDEBUG3,std:cout,"debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +//! } +//! return 0; +//! } +//! catch(const std::exception& e) +//! { +//! UBLOG(logERROR) << e.what(); +//! } +//! \endcode +//! Idee based on: +//! Paper by Dr. Dobbs Portal, +//! September 05, 2007, +//! Logging In C++ +//! +////////////////////////////////////////////////////////////////////////// +template <typename OutputPolicy> +class UbLogger +{ +public: + typedef OutputPolicy output_policy; +public: + UbLogger(); + virtual ~UbLogger(); + std::ostringstream& get(const LogLevel& level = logINFO); +public: + //static, weil man so später die ObjErstellunge ersparen kann, + //falls level kleiner als Level + static LogLevel& reportingLevel(); + + static std::string logLevelToString(const LogLevel& level); + static LogLevel logLevelFromString(const std::string& level); + + static std::string logTimeString(); + +protected: + std::ostringstream os; + +private: + UbLogger(const UbLogger&); + UbLogger& operator =(const UbLogger&); +}; + +////////////////////////////////////////////////////////////////////////// +// template <typename OutputPolicy> class Log - implementation +////////////////////////////////////////////////////////////////////////// +template <typename OutputPolicy> +UbLogger<OutputPolicy>::UbLogger() +{ +} +/*==========================================================*/ +template <typename OutputPolicy> +std::ostringstream& UbLogger<OutputPolicy>::get(const LogLevel& level) +{ + os << logTimeString() << " " << std::setw(6) +#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING) + <<boost::this_thread::get_id() << " " +#endif + << std::setw(8) << std::left << UbLogger<OutputPolicy>::logLevelToString(level) << ": " + << std::string(level > logDEBUG ? 3*(level - logDEBUG) : 0, ' '); //<baumartiger output :D + + return os; +} +/*==========================================================*/ +template <typename OutputPolicy> +UbLogger<OutputPolicy>::~UbLogger() +{ + os << std::endl; + OutputPolicy::output(os.str()); +} +/*==========================================================*/ +template <typename OutputPolicy> +LogLevel& UbLogger<OutputPolicy>::reportingLevel() +{ + static LogLevel reportLevel = logINFO; + return reportLevel; +} +/*==========================================================*/ +template <typename OutputPolicy> +std::string UbLogger<OutputPolicy>::logLevelToString(const LogLevel& level) +{ + static std::string const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"}; + return buffer[level]; +} +/*==========================================================*/ +template <typename OutputPolicy> +LogLevel UbLogger<OutputPolicy>::logLevelFromString(const std::string& level) +{ + if (level == "DEBUG5" ) return logDEBUG5; + if (level == "DEBUG4" ) return logDEBUG4; + if (level == "DEBUG3" ) return logDEBUG3; + if (level == "DEBUG2" ) return logDEBUG2; + if (level == "DEBUG1" ) return logDEBUG1; + if (level == "DEBUG" ) return logDEBUG; + if (level == "INFO" ) return logINFO; + if (level == "WARNING") return logWARNING; + if (level == "ERROR" ) return logERROR; + + UbLogger<OutputPolicy>().get(logWARNING) << "UbLogger<OutputPolicy>::logLevelFromString(level) - unknown logging level '" << level << "'. Using INFO level as default."; + return logINFO; +} + +////////////////////////////////////////////////////////////////////////// +// logTimeString +////////////////////////////////////////////////////////////////////////// +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__WIN64__) +template <typename OutputPolicy> +inline std::string UbLogger<OutputPolicy>::logTimeString() +{ + const int MAX_LEN = 200; + char buffer[MAX_LEN]; + if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, "HH':'mm':'ss", buffer, MAX_LEN) == 0 ) + { + return "Error in std::string UbLogger<OutputPolicy>::logTimeString()"; + } + + char result[100] = {0}; + static DWORD first = GetTickCount(); + std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); + return result; +} +#else +template <typename OutputPolicy> +inline std::string UbLogger<OutputPolicy>::logTimeString() +{ + char buffer[11]; + time_t t; + time(&t); + tm r = {0}; + strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r)); + struct timeval tv; + gettimeofday(&tv, 0); + char result[100] = {0}; + std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); + return result; +} +#endif + + +////////////////////////////////////////////////////////////////////////// +//! Implementation of OutputPolicy) +////////////////////////////////////////////////////////////////////////// +class Output2Stream // implementation of OutputPolicy +{ +public: + static std::ostream*& getStream(); + static void output(const std::string& msg); + + //!creates output-file-stream (of file opening fails -> stream is set to std::cerr) + static void setStream(const std::string& filename); + + //!direct set outputstream, gcControl = true -> object will be deleted by Output2Stream + static void setStream(std::ostream* pStream, const bool& gcControl = false); + +protected: +#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING) + static boost::mutex mtx; +#endif +}; +/*==========================================================*/ +inline std::ostream*& Output2Stream::getStream() +{ + static std::ostream* pStream = &std::clog; + return pStream; +} +/*==========================================================*/ +inline void Output2Stream::setStream(std::ostream* pFile, const bool& gcControl) +{ +#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING) + boost::mutex::scoped_lock lock(mtx); +#endif + static bool s_gcControl = false; + + if( s_gcControl && Output2Stream::getStream() ) + { + delete Output2Stream::getStream(); + } + + s_gcControl = gcControl; + + Output2Stream::getStream() = pFile; +} +/*==========================================================*/ +inline void Output2Stream::setStream(const std::string& filename) +{ + std::ofstream* file = new std::ofstream( filename.c_str() ); + if( !(*file) ) + { + delete file; + Output2Stream::setStream(&std::cerr, false); + UbLogger<Output2Stream>().get(logERROR) << " Output2Stream::setStream(const std::string& filename) could not open file " + << filename << " -> std::cerr is used instead " << std::endl; + return; + } + std::cout<<"UbLog writes to "<<filename<<std::endl; + Output2Stream::setStream(file,true); +} +/*==========================================================*/ +inline void Output2Stream::output(const std::string& msg) +{ +#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING) + boost::mutex::scoped_lock lock(mtx); +#endif + std::ostream* pStream = getStream(); + if (!pStream) return; + (*pStream) << msg << std::flush; +} + +////////////////////////////////////////////////////////////////////////// +// UbLog +////////////////////////////////////////////////////////////////////////// +class UbLog : public UbLogger< Output2Stream > +{ + +}; + +//Macro to limit compiler-side maxLevel +#ifndef UBLOG_MAX_LEVEL + #define UBLOG_MAX_LEVEL logDEBUG5 +#endif + +////////////////////////////////////////////////////////////////////////// +// example UBLOG(logINFO) << "das ist ein log eintrag"; +////////////////////////////////////////////////////////////////////////// +#define UBLOG(level, logtext) \ + if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \ + else UbLog().get(level) << logtext; + +////////////////////////////////////////////////////////////////////////// +//makro 2 fuer korrekten MultiLineOutput (teuer!!) +// example1: UBLOGML(logINFO, "line1"<<endl<<"line2"<<endl<<"line3" ) +// example2: UBLOGML(logINFO, "line1\nline2\nendl\nline3" ) +////////////////////////////////////////////////////////////////////////// +#define UBLOGML(level, multiline) \ + if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \ + else \ + { \ + std::ostringstream output; \ + output << multiline; \ + std::istringstream input( output.str() ); \ + while(!input.eof()) \ + { \ + std::string dummy; \ + getline(input,dummy,'\n'); \ + UbLog().get(level) << dummy; \ + } \ + } +////////////////////////////////////////////////////////////////////////// +//makro3, falls auch bildschirmausgabe erwünscht +// -> es wird sowohl ins logfile als auch auf den "stream" geschrieben +// wenn reporting level und level passen :D +//example1: UBLOG2ML(logINFO, std::cout, "line1"<<endl<<"line2"<<endl<<"line3" ) +//example2: UBLOG2ML(logINFO, std::cout, "line1\nline2\nendl\nline3" ) +////////////////////////////////////////////////////////////////////////// +#define UBLOG2(level, stream, text ) \ + if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \ + else { stream << text <<std::endl; UbLog().get(level) << text; } + +////////////////////////////////////////////////////////////////////////// +//makro4, wie 3 nur mit multiline +//example: UBLOG2(logINFO, std::cout, "test" ) +////////////////////////////////////////////////////////////////////////// +#define UBLOG2ML(level, stream, multiline ) \ + if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \ + else \ + { \ + stream << multiline << std::endl; \ + std::ostringstream output; \ + output << multiline; \ + std::istringstream input( output.str() ); \ + while(!input.eof()) \ + { \ + std::string dummy; \ + getline(input,dummy,'\n'); \ + UbLog().get(level) << dummy; \ + } \ + } + +////////////////////////////////////////////////////////////////////////// +// example 2 +////////////////////////////////////////////////////////////////////////// +// try +// { +// UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG3"); +// //UbLog::output_policy::setStream(&std::cerr); //<- clog ist stdandard +// UbLog::output_policy::setStream("c:/temp/out.txt"); //kann man diese nicht oeffnen -> fehlermeldung -> Log wird in cerr ausgegben +// +// int count = 3; +// UBLOG(logINFO, "A loop with " << count << " iterations"); +// for (int i = 0; i != count; ++i) +// { +// UBLOG(logERROR , "error - the counter i = " << i ); +// UBLOG(logDEBUG1, "debug1 - the counter i = " << i ); +// UBLOG(logDEBUG2, "debug2 - the counter i = " << i ); +// UBLOG(logDEBUG3, "debug3 - the counter i = " << i ); +// //fuer MultiLine Eintraege: --> koerrekte formatierung im logfile +// UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +// UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +// UBLOG2ML(logDEBUG3,std:cout,"debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i); +// } +// return 0; +// } +// catch(const std::exception& e) +// { +// UBLOG(logERROR) << e.what(); +// } + + +#endif //UBLOGGER_H diff --git a/VirtualFluidsBasics/basics/utilities/UbMath.cpp b/VirtualFluidsBasics/basics/utilities/UbMath.cpp new file mode 100644 index 0000000000000000000000000000000000000000..938360645be1ba72aed2f3f4d56ab9f5027244c9 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbMath.cpp @@ -0,0 +1,38 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbMath.cpp +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbInfinity.h> +#include <cstring> //for memcmp + + +const double UbMath::PI = 4.0* std::atan(1.0); //3.1415926535897932384626433832795 diff --git a/VirtualFluidsBasics/basics/utilities/UbMath.h b/VirtualFluidsBasics/basics/utilities/UbMath.h new file mode 100644 index 0000000000000000000000000000000000000000..0261256287952460ba8e1ab8547635f01a203d3b --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbMath.h @@ -0,0 +1,480 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbMath.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBMATH_H +#define UBMATH_H + +#include <cmath> +#include <limits> +#include <iostream> +#include <cassert> +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbEqual.h> + +namespace UbMath +{ + extern const double PI; + + + ////////////////////////////////////////////////////////////////////////// + //Hilfsfunktion fuer Genauigkeit + template< typename T > + struct Epsilon { }; + + ////////////////////////////////////////////////////////////////////////// + // SPECIALIZATIONS von Epsilon + ////////////////////////////////////////////////////////////////////////// + template<> + struct Epsilon<double> { static inline double val() { return 1.0E-11; } }; + template<> + struct Epsilon<float> { static inline float val() { return 1.0E-7f; } }; + template<> + struct Epsilon<long double> { static inline long double val() { return 1.0E-15; } }; + template<> + struct Epsilon<int> { static inline int val() { return 0; } }; + + /*=======================================================*/ + // ------------------------------------------------------------------------------------------------- + // Funktion berechnet den Logarithmus einer Zahl z bzgl. der Basis b + // ------------------------------------------------------------------------------------------------- + template<typename T> + inline T log(const T& z, const T& base) + { + if( ::log(base)==0 ) return 1.0f; + return ::log(z) / ::log(base); + } + /*=======================================================*/ + //double x = UbMath::getNegativeInfinity<double>(); + template<typename T> + inline T getNegativeInfinity() + { + //assert(std::numeric_limits<T>::has_infinity); + UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity); + return -std::numeric_limits<T>::infinity(); + } + /*=======================================================*/ + //double x = UbMath::getPositiveInfinity<double>(); + template<typename T> + inline T getPositiveInfinity() + { + //assert(std::numeric_limits<T>::has_infinity); + UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity); + return std::numeric_limits<T>::infinity(); + } + /*=======================================================*/ + //double x; bool b = UbMath::isInfinity(x); + template<typename T> + inline bool isInfinity(const T& value) + { + if(value==getNegativeInfinity<T>()) return true; + if(value==getPositiveInfinity<T>()) return true; + return false; + } + /*=======================================================*/ + //double x = UbMath::getNaN<double>(x); + template<typename T> + inline T getNaN() + { + UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN); + return std::numeric_limits<T>::quiet_NaN(); + } + /*=======================================================*/ + //double x; bool b = UbMath::isNaN(x); + // x!=x liefert bei #QNAN "true"! + template<typename T> + inline bool isNaN(const T& x) + { + UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN); + return (x != x); + } + /*=======================================================*/ + template<typename T> + inline T getEqualityEpsilon() + { + return Epsilon<T>::val(); + } + /*=======================================================*/ + template<typename T> + inline bool zero(const T& value) + { + return std::fabs( value ) < Epsilon<T>::val(); + //return value >= -UbMath::EPSILON && value <= UbMath::EPSILON; + } + /*=======================================================*/ + //spezialisierung fuer ints + template<> + inline bool zero(const int& value) + { + return value == 0; + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool zero(const T1& value1, const T2& value2) + { + return !(!UbMath::zero(value1) || !UbMath::zero(value2)); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3> + inline bool zero(const T1& value1, const T2& value2, const T3& value3) + { + return !(!UbMath::zero(value1) || !UbMath::zero(value2,value3)); + } + /*=======================================================*/ + template<typename T> + inline bool negative(const T& value) + { + return value < -Epsilon<T>::val(); + } + /*=======================================================*/ + template<typename T> + inline bool nonPositive(const T& value) + { + return value <= Epsilon<T>::val(); + } + /*=======================================================*/ + template<typename T> + inline bool positive(const T& value) + { + return value > +Epsilon<T>::val(); + } + /*=======================================================*/ + template<typename T> + inline bool nonNegative(const T& value) + { + return value >= -Epsilon<T>::val(); + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool equal(const T1& value, const T2& reference) + { + typedef typename UbEqualTrait<T1,T2>::High High; + return std::fabs(value-reference) < Epsilon<High>::val(); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3> + inline bool equal(const T1& val1, const T2& val2, const T3& val3) + { + return ( UbMath::equal(val1,val2) && UbMath::equal(val1,val3) ); + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool less(const T1& value, const T2& reference) + { + typedef typename UbEqualTrait<T1,T2>::High High; + return value < reference - Epsilon<High>::val(); + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool lessEqual(const T1& value, const T2& reference) + { + typedef typename UbEqualTrait<T1,T2>::High High; + return value <= reference + Epsilon<High>::val(); + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool greater(const T1& value, const T2& reference) + { + typedef typename UbEqualTrait<T1,T2>::High High; + return value > reference + Epsilon<High>::val(); + } + /*=======================================================*/ + template<typename T1, typename T2> + inline bool greaterEqual(const T1& value, const T2& reference) + { + typedef typename UbEqualTrait<T1,T2>::High High; + return value >= reference - Epsilon<High>::val(); + } + /*=======================================================*/ + template<typename T> + inline T round(const T& value, const int& decimalPlaces) + { + return static_cast<T>(floor(value * pow( 10.0, decimalPlaces) + 0.5 ) * pow(10.0, -decimalPlaces)); + } + /*=======================================================*/ + template<typename T> + inline int integerRounding(const T& value) + { + return static_cast<int>( UbMath::zero(value) ? 0 : ( (value<0.0) ? (value-0.5) : (value+0.5) ) ); + } + /*=======================================================*/ + template<typename T> + inline T getRad(const T& degrees) + { + return degrees*static_cast<T>(UbMath::PI/180.0); + } + /*=======================================================*/ + template<typename T> + inline T getDegrees(const T& rad) + { + return rad*static_cast<T>(UbMath::PI/180.0); + } + /*=======================================================*/ + //aus wildmagic + template<typename T> + inline T ACos (const T& fValue) + { + if ( -1.0 < fValue ) + { + if ( fValue < 1.0 ) return static_cast<T>( acos(fValue) ); + else return static_cast<T>( 0.0 ); + } + else return static_cast<T>( PI ); + } + /*=======================================================*/ + template<typename T> + inline T ASin(const T& fValue) + { + double HALF_PI = 0.5*UbMath::PI; + if ( -1.0 < fValue ) + { + if ( fValue < 1.0 ) return static_cast<T>( asin(fValue) ); + else return static_cast<T>( HALF_PI ); + } + else return -static_cast<T>( HALF_PI ); + } + /*=======================================================*/ + template<typename T> + inline T invSqrt(const T& fValue) + { + return static_cast<T>(1.0/sqrt(fValue)); + } + + /*=======================================================*/ + /** + * Returns true, if specified values a and b are less both values c and d. + * @param a the first value to check + * @param b the second value to check + * @param c the first value to check against + * @param d the second value to check against + * @return true, if specified values a and b are less both values c and d + **/ + template<typename T1, typename T2, typename T3, typename T4> + inline bool less2(const T1& value1, const T2& value2, T3 toBeLessAs1, T4 toBeLessAs2) + { + return ( less(value1,toBeLessAs1) + && less(value1,toBeLessAs2) + && less(value2,toBeLessAs1) + && less(value2,toBeLessAs2) ); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3, typename T4> + inline bool greater2(const T1& value1, const T2& value2, T3 toBeGreaterAs1, T4 toBeGreaterAs2) + { + return ( greater(value1,toBeGreaterAs1) + && greater(value1,toBeGreaterAs2) + && greater(value2,toBeGreaterAs1) + && greater(value2,toBeGreaterAs2) ); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3> + inline bool inClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2) + { + if(threshold1 < threshold2) + { + return ( greaterEqual( value, threshold1) && lessEqual( value, threshold2) ); + } + + return ( greaterEqual( value, threshold2) && lessEqual( value, threshold1) ); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3> + inline bool inOpenInterval(const T1& value, const T2& threshold1, const T3& threshold2) + { + if(threshold1 < threshold2) + { + return (greater( value, threshold1) && less( value, threshold2)); + } + + return (greater( value, threshold2) && less( value, threshold1)); + } + /*=======================================================*/ + template<typename T1, typename T2, typename T3> + inline double adaptToClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2) + { + if(threshold1 < threshold2) + { + if ( less( value, threshold1) ) return threshold1; + else if( greater(value, threshold2) ) return threshold2; + } + else + { + if ( less( value, threshold2) ) return threshold2; + else if( greater(value, threshold1) ) return threshold1; + } + return value; + } + /*=======================================================*/ + // ------------------------------------------------------------------------------------------------- + // Funktion berechnet den groessten gemeinsamen Teiler zweier Zahlen (MK) + // ------------------------------------------------------------------------------------------------- + /*=======================================================*/ + inline int calcGgt(int val1, int val2) + { + if( val1 < val2 ) std::swap(val1,val2); + int ggt=val2; + while(ggt > 1) + { + if( (val1%ggt)==0 && (val2%ggt)==0 ) break; + + ggt -=1; + } + return ggt; + } + /*=======================================================*/ + // ------------------------------------------------------------------------------------------------- + // Funktion berechnet den groessten gemeinsamen Teiler von drei Zahlen (MK) + // ------------------------------------------------------------------------------------------------- + inline int calcGgt(int val1, const int& val2, int val3) + { + return UbMath::calcGgt( UbMath::calcGgt(val1, val2), val3 ); + } + /*=======================================================*/ + //returns the max of c2 values + //to avoid errors at mixed argument-types use: double myMax = max<double>(2,2.3); + template< typename T > + inline const T& max(const T& a1, const T& a2) + { + return (a1<a2) ? a2 : a1; + } + /*=======================================================*/ + template< typename T > + inline const T& max(const T& a1, const T& a2, const T& a3) + { + return max(max(a1,a2),a3); + } + /*=======================================================*/ + template< typename T > + inline const T& max(const T& a1, const T& a2, const T& a3, const T& a4) + { + return max(max(max(a1,a2),a3),a4); + } + /*=======================================================*/ + template< typename T > + inline const T& min(const T& a1,const T& a2) + { + return (a1<a2) ? a1 : a2; + } + /*=======================================================*/ + template< typename T > + inline const T& min(const T& a1, const T& a2, const T& a3) + { + return min(min(a1,a2),a3); + } + /*=======================================================*/ + template< typename T > + inline const T& min(const T& a1, const T& a2, const T& a3, const T& a4) + { + return min(min(min(a1,a2),a3),a4); + +// double tmp = a1; +// if(tmp>a2) tmp=a2; +// if(tmp>a3) tmp=a3; +// if(tmp>a4) tmp=a4; +// return tmp; + } + + ////////////////////////////////////////////////////////////////////////// + // + //constants + // + ////////////////////////////////////////////////////////////////////////// + static const double c8o27 = 8. / 27.; + static const double c2o27 = 2. / 27.; + static const double c1o54 = 1. / 54.; + static const double c1o216 = 1. / 216.; + static const double c9o2 = 9. / 2.; //4.5 + static const double c9o4 = 9. / 4.; //2.25 + static const double c3o9 = 3. / 9.; + static const double c3o54 = 3. / 54.; + static const double c3o216 = 3. / 216.; + + static const double c1o27 = 1. / 27.; + + static const double c1o72 = 1. / 72.; //0.01388888 + static const double c1o36 = 1. / 36.; //0.02777777 + static const double c1o48 = 1. / 48.; //0.02083333 + static const double c1o32 = 1. / 32.; //0.03125 + static const double c1o24 = 1. / 24.; //0.04166666 + static const double c1o20 = 1. / 20.; //0.05 + static const double c1o18 = 1. / 18.; //0.05555555 + static const double c1o16 = 1. / 16.; //0.0625 + static const double c1o12 = 1. / 12.; //0.08333333 + static const double c1o9 = 1. / 9.; //0.11111111 + static const double c1o8 = 1. / 8.; //0.125 + static const double c1o6 = 1. / 6.; //0.16666666 + static const double c1o5 = 1. / 5.; //0.2 + static const double c1o4 = 1. / 4.; //0.25 + static const double c1o100 = 1. / 100.; + static const double c5o16 = 5. / 16.; //0.3125 + static const double c1o3 = 1. / 3.; //0.33333333 + static const double c3o8 = 3. / 8.; //0.375 + static const double c4o9 = 4. / 9.; //0.44444444 + static const double c1o2 = 1. / 2.; //0.5 + static const double c9o16 = 9. / 16.; //0.5625 + static const double c2o3 = 2. / 3.; //0.66666666 + static const double c3o4 = 3. / 4.; //0.75 + static const double c3o2 = 3. / 2.; //1.5 + static const double c4o3 = 4. / 3.; //1.33333333 + static const double c5o3 = 5. / 3.; //1.66666666 + static const double c9o5 = 9. / 5.; //1.8 + static const double c2o9 = 2. / 9.; //0.22222222 + static const double one_over_sqrt2 = 1.0 / sqrt(2.0); //0.707106781 + static const double one_over_sqrt3 = 1.0 / sqrt(3.0); //0.577350269 + static const double sqrt2 = sqrt(2.0); //1.4142135 + static const double sqrt3 = sqrt(3.0); //1.7320508 + static const double zeroReal = 0.0; + static const double c1 = 1.0; + static const double c2 = 2.0; + static const double c3 = 3.0; + static const double c4 = 4.0; + static const double c5 = 5.0; + static const double c6 = 6.0; + static const double c7 = 7.0; + static const double c8 = 8.0; + static const double c9 = 9.0; + static const double c14 = 14.0; + static const double c15 = 15.0; + static const double c16 = 16.0; + static const double c18 = 18.0; + static const double c21 = 21.0; + static const double c24 = 24.0; + static const double c28 = 28.0; + static const double c29 = 29.0; + static const double c36 = 36.0; + static const double c48 = 48.0; + static const double c50 = 50.0; + static const double c56 = 56.0; + static const double c152 = 152.0; + static const double c130 = 130.0; +} + +#endif diff --git a/VirtualFluidsBasics/basics/utilities/UbObservable.h b/VirtualFluidsBasics/basics/utilities/UbObservable.h new file mode 100644 index 0000000000000000000000000000000000000000..37cb954ddc16c0f258f553375bd46bab48da23a1 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbObservable.h @@ -0,0 +1,270 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbObservable.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBOBSERVABLE_H +#define UBOBSERVABLE_H + +#include <list> +#include <iostream> + +#include <basics/utilities/UbObserver.h> + +class UbObserver; + +////////////////////////////////////////////////////////////////////////// +//! +//! \brief Observable object +//! \details This class provides Observables. The Observeres which observe this +//! Observable are stored in an observerlist. +//! IMPORTANT: objectWillBeDeleted is called at UbObserver::~UbObserver +//! this destructor is called AFTER the destructor of the +//! child classes. if you down_cast the pointer sent with the +//! objectWillBeDeleted(UbObserver* objpointer) then have to go this: +//! +//! if(dynamic_cast<UbObserver*>(observedObj)==objpointer) +//! (e.g.) observedObj=NULL; +//! example: see end of file +//! +//! a copy of an UbservableObject will NOT copy the observerList +//! <UL> +//! <LI><B>Extending:</B> This UbObservable is the observable object itself. Extending should be used +//! where object types can be extended from UbObservable. +//! <LI><B>Associating:</B> Initialization is done via the constructor <tt>UbObservable(ObservableObject)</tt>. +//! Associating may be used, where object types to be observed could not be extended from UbObservable. +//! </UL> +//! +//! see UbObserver +//! +////////////////////////////////////////////////////////////////////////// + +class UbObservable +{ +protected: + /*======================================================================*/ + /* Konstruktoren */ + /* */ + /** + Creates a UbObservable itself to be the object to be observed. + Usually this constructor is used in extended classes. + */ + UbObservable() + { + } + + UbObservable(const UbObservable& src) + { + //no copy of observers !!! + } + + //falls irgendein schlaumeier den =operator von UbObservable aufrufen sollte, + //dann macht diesr auch keine kopie! (Allg: zuweisungsoperatoren werden nie vererbt + UbObservable& operator=(const UbObservable& src) + { + return *this; + } + + // /** + // Creates a UbObservable for the specified Object to be observed. + // Usually this constructor is used in associating UbObservable. + // @param object Object to be observed + // */ +public: + /*======================================================================*/ + /* Destruktor */ + /* */ + /** + */ + virtual ~UbObservable() + { + this->notifyObserversObjectWillBeDeleted(); + } + + /*======================================================================*/ + /* methods */ + /* */ + + /** + Adds an UbObserver to the observerlist. + @param observer the observer to add to this observable (note that an observer may observe c1 observable more than once) + */ + virtual void addObserver(UbObserver* observer) + { + if(!observer) return; + for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos) + { + if(*pos == observer) return; + } + this->mObserverList.push_back(observer); + } + /** + Deletes an UbObserver from the observerlist. + @param observer the observer to remove from this observable (note that all observers identical are deleted) + ( delete means delete Heap... but here we're only removing a pointer) + */ + virtual void removeObserver(UbObserver* observer) + { + if(!observer) return; + this->mObserverList.remove(observer); + + } + /** + Deletes all Observers from the observerlist. + ( delete means delete Heap... but here we're only removing a pointer) + */ + virtual void removeAllObservers() + { + this->mObserverList.clear(); + } + + /** + Checks whether the specified UbObserver observes this observable. + @param observer the observer to remove from this observable (note that all observers identical are deleted) + @return true if the specified observer observes this observable + */ + virtual bool isObservedBy(UbObserver* observer) + { + if(!observer) return false; + for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos) + { + if(*pos == observer) return true; + } + return false; + } + /** + Notifies all of its observers that something happened. Does nothing, if the observed object is null. + Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter. + The Method UbObserver.objectChanged(Object) must be defined + by each class implementing the interface TiObserver + */ + virtual void notifyObserversObjectChanged() + { + std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend + //objectChanged() removed wird... + for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();) + { + //cout<<"in notifyObserversObjectChanged\n"; + //cout<<this->mObserverList.size()<<endl; + + tmp_pos = pos++; // erst tmp_pos=pos und dann pos++ + (*tmp_pos)->objectChanged(this); + } + } + + std::list<UbObserver*>* getObserverList() { return &mObserverList;} + + virtual std::string toString() { return "UbObservable - toString()"; } + +private: + /** + Notifies all of its observers that something happened. Does nothing, if the observed object is null. + Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter. + The Method UbObserver.objectChanged(Object) must be defined + by each class implementing the interface TiObserver + */ + virtual void notifyObserversObjectWillBeDeleted() + { + std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend + //objectWillBeDeleted() removed wird... + for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();) + { + //cout<<"in notifyObserversObjectWillBeDeleted\n"; + //cout<<this->mObserverList.size()<<endl; + + tmp_pos = pos++; + (*tmp_pos)->objectWillBeDeleted(this); + } + } + + std::list<UbObserver*> mObserverList; +}; +/*=========================================================================*/ + + +#ifdef RCF_USE_SF_SERIALIZATION + SF_NO_CTOR(UbObservable); +#endif //RCF_USE_SF_SERIALIZATION + +#endif + +//// E X A M P L E +////=================== +//class Point : public UbObservable +//{ +//public: +// Point(){x=y=0;} +// ~Point(){} +// void setXCorrdinates(int x,int y) +// { +// this->x = x; this->y = y; +// this->notifyObserverObjectChanged(); +// } +//private: +// int x,y; +//}; +//class VisPoint : public UbObserver +//{ +//public: +// VisPoint(Point* point) +// { +// this->point = point; +// this->point->addObserver(this); +// } +// ~VisPoint() +// { +// if(this->point) point->removeObserver(this); +// } +// void update() { /* do some actualisation stuff */ } +// void objectChanged(UbObservable* changedObject) +// { +// Point* point = dynamic_cast<Point*>(changedObject); +// if( !this->point || this->point != point ) return; +// this->repaint(); +// } +// void objectWillBeDeleted(UbObservable* objectForDeletion) +// { +// if(!this->point) return; +// UbObservable* obsobjet = dynamic_cast<UbObservable*>(this->point); +// if(obsobjet == objectForDeletion) this->point = NULL; +// /////////////////////////////////////////////////////////////////// +// //*********************************************************************// +// //INGEGEN erster annahmen nicht verwenden, da es nicht immer funktioniert +// //z.B. bei mehrfachvererbung haut es nicht hin! +// //// Point* point = reinterpret_cast<point*>(objectForDeletion); +// ////if(!this->point || objectForDeletion != this->point) return; +// ////this->point = NULL; +// //*********************************************************************// +// //was hingegen immer moeglich sein sollte: +// //if(dynamic_cast<void*>(objectForDeletion)==dynamic_cast<void*>(this->point)) +// } +//private: +// Point* point; +//}; diff --git a/VirtualFluidsBasics/basics/utilities/UbObserver.h b/VirtualFluidsBasics/basics/utilities/UbObserver.h new file mode 100644 index 0000000000000000000000000000000000000000..6aff49a396a3858028799a9c7d5186a1d80ce4a7 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbObserver.h @@ -0,0 +1,78 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbObserver.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBOBSERVER_H +#define UBOBSERVER_H + +class UbObservable; + +////////////////////////////////////////////////////////////////////////// +//! +//! \brief Observer +//! \details This interface must be implemented by classes which want to +//! observe other objects. +//! IMPORTANT: if you delete an observer, ensure to remove Observer from +//! all his observed observable objects before!!! +//! example: see end of UbObservable.h-file +//! +////////////////////////////////////////////////////////////////////////// + +class UbObserver +{ +protected: + + UbObserver(){} + +public: + + virtual ~UbObserver(){} + + /*======================================================================*/ + /* Methods */ + /* */ + /*! + This function is called when the observable indicated that an object + has changed. + \param changedObject Object which has changed + */ + virtual void objectChanged(UbObservable* changedObject)=0; + /*! + This function is called when the observable indicated that an object + should be deleted. + \param objectForDeletion Object which should be deleted + */ + virtual void objectWillBeDeleted(UbObservable* objectForDeletion)=0; +}; + +#endif + + diff --git a/VirtualFluidsBasics/basics/utilities/UbScheduler.h b/VirtualFluidsBasics/basics/utilities/UbScheduler.h new file mode 100644 index 0000000000000000000000000000000000000000..1bb41a94281d73eed670572dd0986de4b24972a5 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbScheduler.h @@ -0,0 +1,346 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbScheduler.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller, Jan Hegewald +//======================================================================================= +#ifndef UBSCHEDULER_H +#define UBSCHEDULER_H + +#include <iostream> +#include <string> +#include <limits> +#include <cassert> +#include <sstream> +#include <iomanip> +#include <algorithm> + +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbInfinity.h> +#include <basics/utilities/UbComparators.h> + +////////////////////////////////////////////////////////////////////////// +//! +//! \brief A class implements scheduling. +//! \details This class is not thread save. +//! +////////////////////////////////////////////////////////////////////////// + +class UbScheduler +{ +public: + class UbSchedule + { + friend class UbScheduler; + public: + UbSchedule() : step(Ub::inf), begin(Ub::inf), end(Ub::inf) { } + UbSchedule(const double& step, const double& begin=0.0, const double& end=Ub::inf) + : step(step), begin(begin), end(end) + { + } + double getStep() const { return this->step; } + double getBegin() const { return this->begin; } + double getEnd() const { return this->end; } + + /*==========================================================*/ + std::string toString() { std::stringstream text; text<<*this; return text.str(); } + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const UbSchedule& schedule) + { + os<<"Schedule[start,end,step]=["<<schedule.begin<<", "<<schedule.end<<", "<<schedule.step<<"]"; + return os; + } + + private: + double step, begin, end; + }; + +public: + UbScheduler() + { + this->initVals(); + } + /*==========================================================*/ + UbScheduler(const double& step,const double& begin=0, const double& end=Ub::inf ) + { + this->initVals(); + this->addSchedule(step,begin,end); + } + /*==========================================================*/ + UbScheduler(const UbSchedule& schedule) + { + this->initVals(); + this->addSchedule(schedule); + } + /*==========================================================*/ + virtual ~UbScheduler() {} + /*==========================================================*/ + inline void addSchedule(const UbSchedule& schedule) + { + this->addSchedule(schedule.step, schedule.begin, schedule.end); + } + /*==========================================================*/ + bool addSchedule(const double& step, const double& begin, double end) + { + if( UbMath::zero(step) || begin>end ) + { + std::cerr<<"UbScheduler::addSchedule - invalid Schedule:\n\t"<<UbSchedule(step, begin, end)<<std::endl; + return false; + } + + if( UbMath::less( end, (double)Ub::inf ) ) + { + //es kann vorkommen, dass man mit dem intervall nicht genau auf den letzten wert kommt + //(z.B. step=2; start=0; end=9; -> ende wird angepasst) + //also wenn end-begin>Ub::inf ist, dann geht es halt nicht.. ein cast in long double half hier nichts + double multiplier=0.0; + double fractpart = modf( (end-begin)/step, &multiplier); + if( !UbMath::zero(fractpart) ) + { + //tmp-speicherung (fuer cerr) + fractpart = end; + //neues ende + end = begin+multiplier*step; + + std::cerr<<"Warning: UbScheduler::addSchedule - " + <<"end of schedule was adapted to intervall \n\t" + <<"from "<< UbSchedule(step, begin, fractpart) <<" to "<< UbSchedule(step, begin, end) <<std::endl; + } + } + + //nu aber: + schedules.push_back(UbSchedule(step, begin, end)); + + if( end>maxT ) maxT = end; + + double potentialDueTime; + if( calcNextDueTimeForSchedule(schedules.back(), lastUsedT, potentialDueTime) + && potentialDueTime < nextDueTime ) + { + nextDueTime = potentialDueTime; + } + + return true; + } + /*==========================================================*/ + //returns true if scheduler contains schedules + bool hasSchedules() const { return !schedules.empty(); } + /*==========================================================*/ + //time bei dem das letzte mal isDue(time) true war + double getLastDueTime() const { return lastDueTime; } + /*==========================================================*/ + //time bei dem das naechste mal isDue(time) true ergibt + double getNextDueTime() const { return nextDueTime; } + /*==========================================================*/ + //maxDueTime (maxTime der Schedules! + double getMaxDueTime() const { return this->maxT; } + /*==========================================================*/ + bool isDue(const double& t) + { + lastUsedT = t; + if( UbMath::greaterEqual(t,nextDueTime) ) + { + //groesser maxT is nicht + if( UbMath::greater(t,maxT) ) return false; + + //temp var + double actDueTime = nextDueTime; + + //um Suche nach nextDueTime bei "Zukunfts-t" zu optimieren, setzt man die "start"-suchzeit auf "t-1": + nextDueTime = t-1; //t-1 deshlab, damit falls z.B. while Schleife nicht durchlaufen wird + //die folgende if Abfrage nicht faelschlicher Weise true ist! + while( UbMath::greaterEqual(t,nextDueTime) && !UbMath::equal(nextDueTime, maxT) ) + { + double tmpNextDueTime = maxT, potentialDueTime=-1.0; + for(std::size_t i=0; i<schedules.size(); i++) + { + if( calcNextDueTimeForSchedule(schedules[i], nextDueTime, potentialDueTime) + && potentialDueTime < tmpNextDueTime ) + { + assert( nextDueTime < potentialDueTime ); + tmpNextDueTime = potentialDueTime; + } + } + actDueTime = nextDueTime; + nextDueTime = tmpNextDueTime; + } + + //wenn t = der aktuuellen oder gar schon der nächstmöglichen ist (hierbei wurde + //zuvor actDueTime und nextDueTime ggf. angepasst) + //Bsp.: nextDuTime war 5, aber für t=400 gilt andere schedule -> Bsp actDue=350 und nextDue 405 + if( UbMath::equal(t,actDueTime) + || UbMath::equal(t,nextDueTime) ) + { + lastDueTime = t; + return true; + } + } + else if( UbMath::lessEqual(t, lastDueTime) ) + { + if(UbMath::equal(t, lastDueTime) ) return true; //braucht man, wenn man für dasselbe t isDue(t) aufruft + else + { + //Fall: Zeit liegt faktisch in der Vergangenheit -> neu initialsisieren + double tmpNextDueTime = maxT, potentialDueTime=-1.0; + for(size_t i=0; i<schedules.size(); i++) + { + if( calcNextDueTimeForSchedule(schedules[i], t-1, potentialDueTime) + && potentialDueTime < tmpNextDueTime ) + { + tmpNextDueTime = potentialDueTime; + } + } + nextDueTime = tmpNextDueTime; + + return UbMath::equal(t, nextDueTime); + } + } + + return false; + } + /*==========================================================*/ + inline double getMinBegin( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin(); + } + /*==========================================================*/ + inline double getMaxBegin( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin(); + } + /*==========================================================*/ + inline double getMinEnd( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd(); + } + /*==========================================================*/ + inline double getMaxEnd( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd(); + } + /*==========================================================*/ + inline double getMinStep( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep(); + } + /*==========================================================*/ + inline double getMaxStep( ) const + { + if( schedules.empty() ) return Ub::inf; + return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep(); + } + /*==========================================================*/ + inline std::string toString() const + { + std::stringstream text; + text<<*this; + return text.str(); + } + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const UbScheduler& scheduler) + { + os<<"UbScheduler\n"; + os<<"Schedule | start | end | intervall "<<std::endl; + for(std::size_t i=0; i<scheduler.schedules.size(); i++) + os<<std::setw(9)<<i<<"|" + <<std::setw(19)<<scheduler.schedules[i].getBegin()<<"|" + <<std::setw(19)<<scheduler.schedules[i].getEnd() <<"|" + <<std::setw(19)<<scheduler.schedules[i].getStep() <<std::endl; + return os; + } + +protected: + /*==========================================================*/ + void initVals() + { + lastUsedT = -Ub::inf; + lastDueTime = -Ub::inf; + nextDueTime = Ub::inf; + maxT = -Ub::inf; + } + /*==========================================================*/ + // calculates next due time for a schedule + // with nextDueTime > searchStart + bool calcNextDueTimeForSchedule(const UbSchedule& schedule, const double& searchStart, double& nextDueTime ) + { + if ( UbMath::greater(searchStart, schedule.end ) ) return false; + else if( UbMath::less( searchStart, schedule.begin) ) nextDueTime = schedule.begin; + else + { + nextDueTime = schedule.begin + ((int)((searchStart-schedule.begin)/schedule.step)+1)*schedule.step; + if( UbMath::less( nextDueTime, searchStart ) + || UbMath::greater(nextDueTime, schedule.end) ) + { + return false; + } + } + return true; + } + +protected: + double lastUsedT; + double lastDueTime; + double nextDueTime; + double maxT; + + std::vector<UbSchedule> schedules; +}; + +typedef UbScheduler::UbSchedule UbSchedule; + +#endif //UBSCHEDULER_H + + + +//int main(int argc, char** argv) +//{ +// UbScheduler writeSchedule; +//// writeSchedule.addSchedule(0,2000,100); +//// writeSchedule.addSchedule(3005,4500,300); +//// writeSchedule.addSchedule(0,10,1); +//// writeSchedule.addSchedule(0,100001,100); +// writeSchedule.addSchedule(0,2,1); +// writeSchedule.addSchedule(0,100001,200); +// +// for(int t = 0; t < 1001; t++) +// { +// if(writeSchedule.isDue(t)) +// { +// cout<<"due@ "<<t<<endl; +// } +// } +// return 0; +//} + diff --git a/VirtualFluidsBasics/basics/utilities/UbSystem.h b/VirtualFluidsBasics/basics/utilities/UbSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..2102bc52acffb4f7e94263a070c86fe3f55f563c --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbSystem.h @@ -0,0 +1,569 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbSystem.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBSYSTEM_H +#define UBSYSTEM_H + +#if defined(_WIN32) || defined(_WIN64) + #define UBSYSTEM_WINDOWS + #include <process.h> + #include <io.h> + #include <direct.h> + //#ifndef _WINSOCK2API_ //ansonsten gibt es mecker bei #include "Windows.h" und ::Sleep() + // #define _WINSOCK2API_ + // #include<WinSock2.h> + //#endif + #include <windows.h> + //#include <Windows.h> + //#include <tchar.h> +#elif defined(__APPLE__) + #define UBSYSTEM_APPLE + #include "dirent.h" + #include "sys/stat.h" + #include <sys/syscall.h> + #include <sys/stat.h> + #include <unistd.h> +#elif (defined(__amd64) || defined(__amd64__) || defined(__unix__)) && !defined(__AIX__) + #define UBSYSTEM_LINUX + #include "dirent.h" + #include <sys/stat.h> + #include <unistd.h> + #include <string.h> +#elif defined(__AIX__) + #define UBSYSTEM_AIX + #include "dirent.h" + #include <unistd.h> + #include <sys/stat.h> + #include <sys/types.h> +#else + #error "UbSystem::UnknownMachine" +#endif + +#if defined(__unix__) && defined(__CYGWIN__) + #define UBSYSTEM_CYGWIN + #include <windows.h> +#else + #include <sys/syscall.h> +#endif + +#if defined(min) || defined(max) //daruch kann man sich spaeter #undef min; #undef max erparen +# error add NOMINMAX to preprocessor defines +#endif + + +#include <iostream> +#include <iomanip> +#include <string> +#include <sstream> +#include <algorithm> +#include <typeinfo> +#include <cctype> //for toupper +#include <ctime> + +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbLogger.h> + +#if defined(CAB_BOOST) +#include <boost/thread.hpp> +#endif // CAB_BOOST + +//DEFINE TO STRING +//e.g. #define FOO hallo +// -> QUOTEME(FOO) == "hallo" +#define _QUOTEME(x) #x +#define QUOTEME(x) _QUOTEME(x) + +//allg.: +//const int * C1 -> C1 is variable pointer to a constant integer +//int const * C2 -> C2 is variable pointer to a constant integer (same as above) +//int * const C3 -> C3 is constant pointer to a variable integer +//int const * const C4 -> C4 is constant pointer to a constant integer + +////////////////////////////////////////////////////////////////////////// +//UbSystem +////////////////////////////////////////////////////////////////////////// +namespace UbSystem +{ + template<bool> struct ub_static_assert; //deklaration (ub_xxx da static_assert in C++0x ein keyword werden wird) + template<> struct ub_static_assert<true>{}; //deklaration + definition der spezialisierung fuer "true" + //ub_static_assert<false> fuehrt zu compiler fehler, da dafuer + //keine implementierung vorhanden! //UB_STATIC_ASSERT(false) + + /*==========================================================*/ + inline void sleepMs(const unsigned int& msec) + { + #if defined(UBSYSTEM_WINDOWS) + ::Sleep( (msec==0) ? 1 : msec ); // +1 here causes a context switch if SleepMSec(0) is called + #elif (defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)) && !defined(UBSYSTEM_CYGWIN) + ::usleep(1000*msec); + #elif defined(UBSYSTEM_CYGWIN) + ::Sleep( (msec==0) ? 1 : msec ); + #else + #error "UbSystem::sleepMSec - UnknownMachine" + #endif + } + /*==========================================================*/ + inline void sleepS(const unsigned int& sec) + { + #if defined(UBSYSTEM_WINDOWS) && defined(UBSYSTEM_CYGWIN) + ::Sleep( (sec==0) ? 1 : sec*1000 ); // +1 here causes a context switch if sleepS(0) is called + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX) && !defined(UBSYSTEM_CYGWIN) + ::sleep(sec); + #else + #error "UbSystem::sleepS - UnknownMachine" + #endif + } + /*==========================================================*/ + //checks if the bits of bitmask are set in value + template<typename T> + inline bool bitCheck(const T& value, const T& bitmask) + { + return ( (value & bitmask) == bitmask); + } + /*==========================================================*/ + //checks if the bits of bitmask are set in value + template<typename T> + inline void setBit(T& value, const T& bitmask) + { + value |= bitmask; + } + /*==========================================================*/ + template<typename T> + inline void unsetBit(T& value, const T& bitmask) + { + value &= ~bitmask; + } + /*==========================================================*/ + //returns bitmask as string e.g. 0001 0100 1101 + template<typename T> + inline std::string getBitString(const T& value) + { + std::stringstream text; + for(int i=sizeof(value)*8-1/*8 bits per byte*/; i>=0; i--) + { + text<<(char) ( ((value>>i) & 1) + '0'); + if(i%4 == 0 && i>0) text<<' '; + } + return text.str(); + } + /*==========================================================*/ + //converts string to type T + // usage: int x = stringTo<int>("123"); + template<typename T> + inline T stringTo(const std::string& s) + { + std::istringstream iss(s); + T x; + iss >> x; + if(!iss) + UB_THROW( UbException(UB_EXARGS," cannot convert \""+s+"\" to type <"+static_cast<std::string>(typeid(x).name())+">") ); + + return x; + } + /*==========================================================*/ + // usage: string s = toString(x); + template<typename T> + inline std::string toString(const T& x, int precision=15) + { + std::ostringstream oss; + oss<<std::setprecision(precision); + oss<<x; + return oss.str(); + } + /*==========================================================*/ + //e.g. str="iHcsnW" -> "IHCSNW" + inline std::string toUpperString(const std::string& str) + { + std::string tmp(str); + std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::toupper)); + + return tmp; + } + /*==========================================================*/ + //e.g. str="iHcsnW" -> "ihcsnw" + inline std::string toLowerString(const std::string& str) + { + std::string tmp(str); + std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::tolower)); + + return tmp; + } + /*==========================================================*/ + // usage: std::string s = replaceInString(str,"\\","/"); + // std::string s = replaceInString(str,"ich","du"); + static std::string replaceInString(std::string original, const std::string& replace, const std::string& replaceWith ) + { + size_t pos=0; + while( (pos=original.find(replace,pos))!=std::string::npos ) + { + original.replace(pos,replace.size(),replaceWith); + pos+=replaceWith.size(); + } + return original; + } + /*==========================================================*/ + //returns content of an enviroment variable + inline std::string getEnv(const std::string& var) + { + char* str = getenv( var.c_str()); + if( str == NULL ) + { + return std::string(""); + } + + return static_cast<std::string>( str ); + } + /*==========================================================*/ + inline bool isDirectory(const std::string& dir, const unsigned& attemptions = 3) + { + if( dir.empty() ) + UB_THROW( UbException(UB_EXARGS,"dir is empty") ); + + std::string path = UbSystem::replaceInString(dir,"\\","/"); + + #if defined UBSYSTEM_WINDOWS + #ifndef _UNICODE + if( _access(path.c_str(), 0 ) == -1 ) return false; + #else + if( _waccess(path.c_str(), 0 ) == -1 ) return false; + #endif + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX) + struct stat stFileInfo; + if( stat(path.c_str(),&stFileInfo) != 0) + { + return false; + } + #endif + + return true; + } + /*==========================================================*/ + // usage: makeDirectory("c:/temp"); + // makeDirectory("c:/temp/"); + // return: true -> successful + // false -> failed + #if defined(CAB_BOOST) + static boost::mutex mtx_makeDirectory; + #endif + inline bool makeDirectory(const std::string& dir, const unsigned& attemptions = 3) + { + UBLOG(logDEBUG5,"UbSystem::makeDirectory - start, dir="<<dir<<" #attemptions="<<attemptions); + + if( dir.empty() ) UB_THROW( UbException(UB_EXARGS,"dir is empty") ); + std::string path = UbSystem::replaceInString(dir,"\\","/"); + + bool dirCreated = true; + #if defined UBSYSTEM_WINDOWS + if(path[path.size()-1] != '/') path+="/"; + size_t pos = 0; + while( ( pos=path.find("/",pos+1) ) != std::string::npos ) + { + std::string tmpdir = path.substr(0,pos); + #if defined(CAB_BOOST) + boost::mutex::scoped_lock lock(mtx_makeDirectory); + #endif + if( + #ifndef _UNICODE + _access(tmpdir.c_str(), 0 ) == -1 && _mkdir(tmpdir.c_str() ) == -1 + #else + _waccess(tmpdir.c_str(), 0) == -1 && _wmkdir(tmpdir.c_str()) == -1 + #endif + ) + { + UBLOG(logDEBUG5,"UbSystem::makeDirectory- dir=\""<<tmpdir<<"\" doesn't exit or makedir failed"); + dirCreated = false; + break; + } + } + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX) + std::string command = "mkdir -p \""+path+"\""; + { + #if defined(CAB_BOOST) + boost::mutex::scoped_lock lock(mtx_makeDirectory); + #endif + if(system(command.c_str())!=0) + { + UBLOG(logDEBUG5,"UbSystem::makeDirectory- dir=\""<<path<<"\" doesn't exit or makedir failed"); + dirCreated = false; + } + } + #else + #error "UbSystem::makeDirectory - UnknownMachine" + #endif + + if(!dirCreated && attemptions > 1) + { + UBLOG(logDEBUG5,"UbSystem::makeDirectory - internal call of UbSystem::makeDirectory"); + UbSystem::sleepMs(500); + dirCreated = UbSystem::makeDirectory(path, attemptions-1); + } + + UBLOG(logDEBUG5,"UbSystem::makeDirectory - end (success="<<dirCreated<<", attemptions = "<<attemptions<<")"); + return dirCreated; + } + /*==========================================================*/ +#if defined(CAB_BOOST) + static boost::mutex mtx_removeDirectory; +#endif + inline int removeDirectory(const std::string& dir) + { + #if defined(CAB_BOOST) + boost::mutex::scoped_lock lock(mtx_removeDirectory); + #endif + std::string command = "rmdir \""+dir+"\""; + return std::system(command.c_str()); + } + /*==========================================================*/ + // usage : getPathFromString("c:/temp/foo.txt"); + //returns: "c:/temp" + // usage : getPathFromString("c:\\temp\\foo.txt"); + //returns: "c:/temp" + // usage : getPathFromString("foo.txt"); + // returns: "" + inline std::string getPathFromString(const std::string& fileStringWithPath) + { + std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/"); + std::size_t last = tmp.rfind("/"); + if(last!=std::string::npos) tmp.resize(last); + else tmp = ""; + return tmp; + } + /*==========================================================*/ + // usage : getFilenameFromString("c:/temp/foo.txt"); + // returns: "foo.txt" + // usage : getFilenameFromString("c:/temp/foo.txt",false); + // returns: "foo" + // usage : getFilenameFromString("c:/temp/"); + // returns: "" + inline std::string getFilenameFromString(const std::string& fileStringWithPath, bool withExtension = true) + { + std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/"); + + //remove path + std::size_t last = tmp.rfind("/"); + if(last!=std::string::npos && (last+1)<tmp.size()) tmp.erase(0,last+1); + + //remove extension + if(!withExtension) + { + last = tmp.rfind("."); + if(last!=std::string::npos) tmp.erase(last); + } + + return tmp; + } + /*==========================================================*/ + inline int getProcessID() + { + #if defined UBSYSTEM_WINDOWS + return _getpid(); + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX) + return getpid(); + #else + #error "int UbSystem::getProcessID() - UnknownMachine" + #endif + } + /*==========================================================*/ + inline unsigned long getCurrentThreadID() + { + #if defined UBSYSTEM_WINDOWS + return (unsigned long)GetCurrentThreadId(); + #elif (defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE)) && !defined(UBSYSTEM_CYGWIN) + return (unsigned long)syscall(SYS_gettid); + #elif defined(UBSYSTEM_CYGWIN) + return (unsigned long)GetCurrentThreadId(); + #elif defined(UBSYSTEM_AIX) + return (unsigned long) getpid(); //WORKAROUND for IBM (for get thread id is another function necessary) + #else + #error "unsigned long UbSystem::getCurrentThreadID() - UnknownMachine" + #endif + } + /*==========================================================*/ + inline bool isBigEndian() + { + short word = 0x4321; + if((*(char*)& word) != 0x21 ) return true; + else return false; + } + /*==========================================================*/ + inline bool isLittleEndian() + { + return !isBigEndian(); + } + /*==========================================================*/ + inline std::string getTimeStamp() + { + time_t t = time(NULL); + tm* localTime = localtime(&t); + + std::stringstream tmp; + tmp.fill('0'); + + tmp << localTime->tm_year+1900 + << "." << std::setw(2) <<localTime->tm_mon+1 + << "." << std::setw(2) << localTime->tm_mday + << "@" << std::setw(2) << localTime->tm_hour + << "." << std::setw(2) << localTime->tm_min + << "." << std::setw(2) << localTime->tm_sec ; + + return tmp.str(); + } + /*==========================================================*/ + //swap Byte Order + //usage: int test = 8; + // swapByteOrder((unsigned char*)& test, sizeof(int)) + //#define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x)) + inline void swapByteOrder(unsigned char* toSwap, int length) + { + register int i = 0; + register int j = length-1; + while(i<j) + { + std::swap(toSwap[i], toSwap[j]); + i++, j--; + } + } + ////////////////////////////////////////////////////////////////////////// + //get host name + inline std::string getMachineName() + { + char Name[150]; + int i = 0; + +#if defined(UBSYSTEM_WINDOWS) && defined(UBSYSTEM_CYGWIN) + TCHAR infoBuf[150]; + DWORD bufCharCount = 150; + memset(Name, 0, 150); + if (GetComputerName(infoBuf, &bufCharCount)) + { + for (i = 0; i<150; i++) + { + Name[i] = infoBuf[i]; + } + } + else + { + strcpy(Name, "Unknown_Host_Name"); + } +#elif (defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)) && !defined(UBSYSTEM_CYGWIN) + memset(Name, 0, 150); + gethostname(Name, 150); +#endif + return std::string(Name); + } + + ////////////////////////////////////////////////////////////////////////// + // generic IfThenElse - start + ////////////////////////////////////////////////////////////////////////// + // primary template: yield second or third argument depending on first argument + template<bool C, typename Ta, typename Tb> + class IfThenElse; + + // partial specialization: true yields second argument + template<typename Ta, typename Tb> + class IfThenElse<true, Ta, Tb> { + public: + typedef Ta ResultT; + }; + + // partial specialization: false yields third argument + template<typename Ta, typename Tb> + class IfThenElse<false, Ta, Tb> { + public: + typedef Tb ResultT; + }; + ////////////////////////////////////////////////////////////////////////// + // generic IfThenElse - end + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + //help struct for overloading methods in template classes for specific types + ////////////////////////////////////////////////////////////////////////// + template< typename T> + struct type2type + { + typedef T type; + }; + + + ////////////////////////////////////////////////////////////////////////// + // pair selector + ////////////////////////////////////////////////////////////////////////// + template <typename Pair> + struct select1st + { + typedef Pair argument_type ; + typedef typename Pair::first_type result_type ; + + const result_type& operator()(const argument_type &p) const + { + return p.first ; + } + }; + + template <typename Pair> + struct select2nd + { + typedef Pair argument_type ; + typedef typename Pair::second_type result_type ; + + const result_type& operator()(const argument_type &p) const + { + return p.second ; + } + }; + +}; + +#define UB_STATIC_ASSERT(expr) static_cast<void>(sizeof( UbSystem::ub_static_assert<expr> )); +//zum ueberpruefen von STATISCHEN ausdruecken waehrend der compile-zeit +//--> Ausdruecke muessen schon ZUR compilerzeit auswertbar sein !!! +//Anwendung z.B. zur Ueberpruefung von Funktionalitaeten, wie z.B. bei UbMath::getNegativeInfinity<double>(); +// +//Grund fuer macro ist einfach, dass es besser anzuwenden ist in der praxis! +//ansonsten w�rde es so aussehen: +// UbSystem::ub_static_assert< aaa == 1 > test(); +// da ist UB_STATIC_ASSERT(aaa == 1); schoener +// +//um das zu vermeiden machtman hier diesen static_cast<void>(sizeof(...) ) +//Code-Snippet: +// struct Test { const static bool m_const_bool = true; bool m_bool; }; +// int main() { +// UB_STATIC_ASSERT( Test::m_const_bool == true ); +// --> okay, assert bestanden +// UB_STATIC_ASSERT( Test::m_const_bool == false); //: +// --> assert nicht bestanden z.B. error C2027: use of undefined type 'UbSystem::ub_static_assert<__formal> with __formal = false --> funzt nicht. fehler im code +// UB_STATIC_ASSERT( Test::m_bool == true ); +// --> nicht erlaubt, da m_bool nicht statisch und nicht const ist. +//} + +#endif //UBSYSTEM_H diff --git a/VirtualFluidsBasics/basics/utilities/UbTiming.h b/VirtualFluidsBasics/basics/utilities/UbTiming.h new file mode 100644 index 0000000000000000000000000000000000000000..d683d07050d9a906adfe3a71d77270d2d8bf034a --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbTiming.h @@ -0,0 +1,416 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbTiming.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBTIMING_H +#define UBTIMING_H + +#include <string> +#include <limits> +#include <iostream> +#include <sstream> +#include <vector> +#include <ctime> + +#ifdef VF_MPI + #include <mpi.h> + #include <basics/parallel/PbMpi.h> +#endif //VF_MPI + +class UbTiming +{ +public: + UbTiming() + { + this->duration = 0.0; + this->deltaT = 0.0; + this->startTime = 0; + this->name = "noname"; + } + /*==========================================================*/ + UbTiming(const std::string& name) + { + this->duration = 0.0; + this->deltaT = 0.0; + this->startTime = 0; + this->name = name; + } + /*==========================================================*/ + virtual ~UbTiming() {} + /*==========================================================*/ + virtual void initTiming() + { + this->duration = 0.0; + } + /*==========================================================*/ + virtual void startTiming() + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->startTime = PbMpi::Wtime(); + #else + this->startTime = (double)clock(); + #endif //VF_MPI + } + /*==========================================================*/ + virtual void initAndStartTiming() + { + this->initTiming(); + this->startTiming(); + } + /*==========================================================*/ + virtual void endTiming() + { + this->stopTiming(); + } + /*==========================================================*/ + virtual void stopTiming() + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->deltaT = PbMpi::Wtime()-this->startTime; + #else + this->deltaT = ((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC; + #endif //VF_MPI + + this->duration += this->deltaT; + } + /*==========================================================*/ + virtual double getDuration() const + { + return this->duration; + } + /*==========================================================*/ + virtual void setName(const std::string& name) + { + this->name = name; + } + /*==========================================================*/ + virtual std::string getName() const + { + return this->name; + } + /*==========================================================*/ + void start() + { + this->duration = 0.0; + + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->startTime = PbMpi::Wtime(); + #else + this->startTime = (double)clock(); + #endif //VF_MPI + } + /*==========================================================*/ + void pause() + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->duration += PbMpi::Wtime()-this->startTime; + #else + this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC; + #endif //VF_MPI + } + /*==========================================================*/ + void unpause() + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->startTime = PbMpi::Wtime(); + #else + this->startTime = (double)clock(); + #endif //VF_MPI + } + /*==========================================================*/ + void stop() + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->duration += PbMpi::Wtime()-this->startTime; + #else + this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC; + #endif //VF_MPI + } + /*==========================================================*/ + double getTicks() const + { + #if defined(VF_MPI) && !defined(CAB_RUBY) + return PbMpi::Wtick(); + #else + return double(1.0)/double(CLOCKS_PER_SEC); + #endif //VF_MPI + } + +protected: + std::string name; + + double startTime; + double duration; + double deltaT; +}; + +#include <basics/utilities/UbSystem.h> //for definitons of system/OS type + +#ifdef UBSYSTEM_APPLE //Apple hack + #include <mach/mach_time.h> + #include <time.h> + #include <stdio.h> + inline void mach_absolute_difference(const uint64_t& end, const uint64_t& start, struct timespec *tp) + { + uint64_t difference = end - start; + static mach_timebase_info_data_t info = {0,0}; + + if (info.denom == 0) + mach_timebase_info(&info); + + uint64_t elapsednano = difference * (info.numer / info.denom); + + tp->tv_sec = elapsednano * 1e-9; + tp->tv_nsec = elapsednano - (tp->tv_sec * 1e9); + } +#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX) + #include <ctime> + #include <unistd.h> // for sysconf + #include <pthread.h> +#endif + +/*=========================================================================*/ +//! \brief Time Measuring +//! \details +//! example: +//! \code +//! t=0 start +//! t=1 +//! t=2 stop -> return 2; getLapTime=2; getTotalTime 2; getLapTimes: 2 +//! t=3 +//! t=4 +//! t=5 stop -> return 3; getLapTime=3; getTotalTime 5; getLapTimes: 2,3 +//! t=6 stop -> return 1; getLapTime=1; getTotalTime 6; getLapTimes: 2,3,1 +//! t=7 +//! t=8 start ->no consideration of time 7 and 8 +//! t=9 +//! t=10 stop -> return 2; getLapTime=2; getTotalTime 8; getLapTimes: 2,3,1,2 +//! t=11 resetAndStart -> Timer is reset and restarted +//! t=12 +//! t=13 +//! t=14 stop -> return 3; getLapTime=3; getTotalTime 3; getLapTimes: 3 +//! \endcode + +class UbTimer +{ +public: + UbTimer(const bool& storeLapTimes = false) + : name("unamed"), isMeasuring(false), storeLapTimes(storeLapTimes) + , startTime(0.0), totalTime(0.0), lapTime(0.0) + { + + } + /*==========================================================*/ + UbTimer(const std::string& name, const bool& storeLapTimes = false) + : name(name), isMeasuring(false), storeLapTimes(storeLapTimes) + , startTime(0.0), totalTime(0.0), lapTime(0.0) + { + + } + /*==========================================================*/ + virtual ~UbTimer() {} + /*==========================================================*/ + double getLapTime() const { return this->lapTime; } + std::vector<double> getLapTimes() const { return this->lapTimes; } + void setName(const std::string& name) { this->name = name; } + std::string getName() const { return this->name; } + bool isRunning() const { return isMeasuring; } + bool isStoringLapTimes() const { return storeLapTimes; } + /*==========================================================*/ + void setStoreLapTimes(const bool& storeLapTimes) { this->storeLapTimes = storeLapTimes; } + /*==========================================================*/ + void start() + { + this->isMeasuring = true; + + #if defined(VF_MPI) && !defined(CAB_RUBY) + this->startTime = PbMpi::Wtime(); + #elif defined(UBSYSTEM_APPLE) + this->startTime = mach_absolute_time(); + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX) + timespec tp; + clock_gettime(CLOCK_REALTIME,&tp); + this->startTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec); + #else + this->startTime = (double)clock(); + #endif //VF_MPI + } + /*==========================================================*/ + void resetAndStart() { this->reset(); this->start(); } + /*==========================================================*/ + //stop: - stops the calculation and returns the time elapsed since last start/stop + // - timing continues + double stop() + { + //if start() was never activated before: + if(!isMeasuring) return 0.0; + + #if defined(VF_MPI) && !defined(CAB_RUBY) + double actTime = PbMpi::Wtime(); + this->lapTime = actTime-this->startTime; + #elif defined(UBSYSTEM_APPLE) + double actTime = mach_absolute_time(); + timespec tp; + mach_absolute_difference(actTime, this->startTime, &tp); + this->lapTime = tp.tv_sec + tp.tv_nsec*1e-9; + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX) + timespec tp; + clock_gettime(CLOCK_REALTIME,&tp); + double actTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec); + this->lapTime = (actTime-this->startTime)*1.0e-9; + #else + double actTime = (double)clock(); + this->lapTime = (actTime-this->startTime)/(double)CLOCKS_PER_SEC; + #endif //VF_MPI + + this->startTime = actTime; + this->totalTime += this->lapTime; + if(storeLapTimes) lapTimes.push_back(this->lapTime); + + return lapTime; + } + /*==========================================================*/ + void reset() + { + this->isMeasuring = false; + + this->startTime = 0.0; + this->totalTime = 0.0; + this->lapTime = 0.0; + + lapTimes.resize(0); + } + /*==========================================================*/ + double getCurrentLapTime() const + { + //if start() was never activated before: + if(!isMeasuring) return 0.0; + + #if defined(VF_MPI) && !defined(CAB_RUBY) + return PbMpi::Wtime() - this->startTime; + #elif defined(UBSYSTEM_APPLE) + timespec tp; + mach_absolute_difference(mach_absolute_time(), this->startTime, &tp); + return tp.tv_sec + tp.tv_nsec*1e-9; + #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX) + timespec tp; + clock_gettime(CLOCK_REALTIME,&tp); + return ((double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec) - this->startTime)*1.0e-9; + #else + return ( (double)clock() - this->startTime ) / (double)CLOCKS_PER_SEC; + #endif //VF_MPI + + } + /*==========================================================*/ + double getTotalTime() const + { + return this->totalTime; + } + /*==========================================================*/ + std::string toString() + { + std::stringstream text; + text<<*this; + return text.str(); + } + + //ueberladene Operatoren + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const UbTimer& timer) + { + os<<"UbTimer[totalTime="<<timer.totalTime<<"sec, lapTimes("; + for(std::size_t i=0; i<timer.lapTimes.size(); i++) os<<timer.lapTimes[i]<<","; + os<<")]"; + return os; + } + + +protected: + std::string name; + bool isMeasuring; + bool storeLapTimes; + + double startTime; + double totalTime; + double lapTime; + + std::vector<double> lapTimes; +}; + + +/*=========================================================================*/ +//! \brief Time Measuring +//! +//! \details UbProressTimer measures the time from its instantiation to destruction and spend the elapsed time on "os" in [s] +//! example: +//! \code +//! { +//! UbProgressTimer timer; +//! UbSystem::sleepS(10); +//! } //--> 10s +//! \endcode + +class UbProgressTimer : public UbTimer +{ +private: + UbProgressTimer(const UbProgressTimer& rhs); +public: + explicit UbProgressTimer( std::ostream & os = std::cout ) + : UbTimer(),os(os) + { + this->start(); + } + /*==========================================================*/ + ~UbProgressTimer() + { + // A) Throwing an exception from a destructor is a Bad Thing. + // B) The progress_timer destructor does output which may throw. + // C) A progress_timer is usually not critical to the application. + // Therefore, wrap the I/O in a try block, catch and ignore all exceptions. + try + { + // use istream instead of ios_base to workaround GNU problem (Greg Chicares) + std::istream::fmtflags old_flags = os.setf( std::istream::fixed, + std::istream::floatfield ); + std::streamsize old_prec = os.precision( 2 ); + os << stop() << " s" << std::endl; + os.flags( old_flags ); + os.precision( old_prec ); + } + catch (...) {} // eat any exceptions + } + +private: + std::ostream & os; +}; + + +#endif //UBTIMING_H diff --git a/VirtualFluidsBasics/basics/utilities/UbTuple.h b/VirtualFluidsBasics/basics/utilities/UbTuple.h new file mode 100644 index 0000000000000000000000000000000000000000..621b378e12a0b37195ec268ce14581576b7de14b --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/UbTuple.h @@ -0,0 +1,632 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbTupel.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef UBTUPLE_H +#define UBTUPLE_H + +#include <iostream> +#include <string> +#include <ostream> + +////////////////////////////////////////////////////////////////////////// +//! \brief A class implements a tuple +//! \details +//! usage: ...<BR> +//! Advanced UbTuple +//! Example: +//! create and use tuple with only c1 field +//! \code +//! UbTuple<int,int,int,int,int> t1; +//! val<1>(t1) += 42; +//! std::cout << t1.v1() << std::endl; +//! \endcode +//! create and use duo: +//! \code +//! UbTuple<bool,int> t2; +//! std::cout << val<1>(t2) << ", "; +//! std::cout << t2.v1() << std::endl; +//! \endcode +//! create and use triple: +//! \code +//! UbTuple<bool,int,double> t3; +//! val<1>(t3) = true; // new values via: val< pos >(triple) = ... +//! val<2>(t3) = 42; +//! val<3>(t3) = 0.2; +//! t3 = makeUbTuple(false, 23, 13.13); +//! +//! std::cout << val<1>(t3) << ", "; +//! std::cout << val<2>(t3) << ", "; +//! std::cout << val<3>(t3) << std::endl; +//! \endcode +//! create and use quadruple: +//! \code +//! UbType<bool,int,float,double> t4(true,42,13,1.95583); +//! std::cout << val<4>(t4) << std::endl; //<- option 2 (std) +//! std::cout << t4.v2().v2().v2() << std::endl; //<- option 2 +//! \endcode + +template <typename T> +class UbTypeOp // primary template +{ +public: + typedef T ArgT; + typedef T BareT; + typedef T const ConstT; + typedef T & RefT; + typedef T & RefBareT; + typedef T const & RefConstT; +}; +/**** end of typeop1.hpp ****/ + +// partial specialization for const +/********************************** +* typeop2.hpp: +**********************************/ +template <typename T> +class UbTypeOp <T const> // partial specialization for const types +{ + public: + typedef T const ArgT; + typedef T BareT; + typedef T const ConstT; + typedef T const & RefT; + typedef T & RefBareT; + typedef T const & RefConstT; +}; +/**** end of typeop2.hpp ****/ + +// partial specialization for references +/********************************** +* typeop3.hpp: +**********************************/ +template <typename T> +class UbTypeOp <T&> // partial specialization for references +{ +public: + typedef T & ArgT; + typedef typename UbTypeOp<T>::BareT BareT; + typedef T const ConstT; + typedef T & RefT; + typedef typename UbTypeOp<T>::BareT & RefBareT; + typedef T const & RefConstT; +}; +/**** end of typeop3.hpp ****/ + +// full specialization for void +/********************************** +* typeop4.hpp: +**********************************/ +template<> +class UbTypeOp <void> // full specialization for void +{ +public: + typedef void ArgT; + typedef void BareT; + typedef void const ConstT; + typedef void RefT; + typedef void RefBareT; + typedef void RefConstT; +}; +/**** end of typeop4.hpp ****/ + +template <typename T1, typename T2> +class UbDuo; + +template <typename T1, typename T2> +std::ostream& operator << (std::ostream& os, UbDuo<T1, T2> const& d1); + +//duo1.hpp +template <typename T1, typename T2> +class UbDuo +{ +public: + typedef T1 Type1; // type of first field + typedef T2 Type2; // type of second field + enum { N = 2 }; // number of fields + +public: + // constructors + UbDuo() : value1(), value2() { } + UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { } + + // for implicit type conversion during construction + template <typename U1, typename U2> + UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { } + + // for implicit type conversion during assignments + template <typename U1, typename U2> + UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) + { + value1 = d.v1();//value1; + value2 = d.v2();//value2; + return *this; + } + + // field access + T1& v1() { return value1; } + T1 const& v1() const { return value1; } + + T2& v2() { return value2; } + T2 const& v2() const { return value2; } + +private: + T1 value1; // value of first field + T2 value2; // value of second field +}; + +// comparison operators (allow mixed types): +template <typename T1, typename T2,typename U1, typename U2> +inline bool operator == (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2) +{ + return d1.v1()==d2.v1() && d1.v2()==d2.v2(); +} + +template <typename T1, typename T2,typename U1, typename U2> +inline bool operator != (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2) +{ + return !(d1==d2); +} + +template <typename T1, typename T2,typename U1, typename U2> +inline bool operator < (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2) +{ + if (d1.v1() < d2.v1() ) return true; + else if(d1.v1() == d2.v1() ) return d1.v2() < d2.v2(); + + return false; +} + +template <typename T1, typename T2> +std::ostream& operator << (std::ostream& os, UbDuo<T1, T2> const& d1) +{ + os << d1.v1() << ", " << d1.v2(); + return os; +} + +// convenience function for creation and initialization +template <typename T1, typename T2> +inline UbDuo<T1,T2> makeUbDuo(T1 const & a, T2 const & b) +{ + return UbDuo<T1,T2>(a,b); +} + +//duo2.hpp +template <typename A, typename B, typename C> +class UbDuo<A, UbDuo<B,C> > +{ +public: + typedef A T1; // type of first field + typedef UbDuo<B,C> T2; // type of second field + enum { N = UbDuo<B,C>::N + 1 }; // number of fields + +public: + // constructors + UbDuo() : value1(), value2() { } + UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { } + + // for implicit type conversion during construction + template <typename U1, typename U2> + UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { } + + // for implicit type conversion during assignments + template <typename U1, typename U2> + UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) + { + value1 = d.v1();//value1; + value2 = d.v2();//value2; + return *this; + } + + // field access + T1& v1() { return value1; } + T1 const& v1() const { return value1; } + + T2& v2() { return value2; } + T2 const& v2() const { return value2; } + +private: + T1 value1; // value of first field + T2 value2; // value of second field +}; + +//duo3.hpp +// primary template for type of Nth field of (duo) T +template <int N, typename T> +class UbDuoT +{ +public: + typedef void ResultT; // in general, the result type is void +}; + +// specialization for 1st field of a plain duo +template <typename A, typename B> +class UbDuoT<1, UbDuo<A,B> > +{ +public: + typedef A ResultT; +}; + +// specialization for 2nd field of a plain duo +template <typename A, typename B> +class UbDuoT<2, UbDuo<A,B> > +{ +public: + typedef B ResultT; +}; + +// specialization for Nth field of a recursive duo +template <int N, typename A, typename B, typename C> +class UbDuoT<N, UbDuo<A, UbDuo<B,C> > > +{ +public: + typedef typename UbDuoT<N-1, UbDuo<B,C> >::ResultT ResultT; +}; + +// specialization for 1st field of a recursive duo +template <typename A, typename B, typename C> +class UbDuoT<1, UbDuo<A, UbDuo<B,C> > > +{ +public: + typedef A ResultT; +}; + +// specialization for 2nd field of a recursive duo +template <typename A, typename B, typename C> +class UbDuoT<2, UbDuo<A, UbDuo<B,C> > > +{ +public: + typedef B ResultT; +}; + +//duo4.hpp +// primary template for value of Nth field of (duo) T +template <int N, typename T> +class DuoValue +{ +public: + static void get(T&) { } // in general, we have no value + static void get(T const&) { } +}; + +// specialization for 1st field of a plain duo +template <typename A, typename B> +class DuoValue<1, UbDuo<A, B> > +{ +public: + static A& get(UbDuo<A, B> &d) { return d.v1(); } + static A const& get(UbDuo<A, B> const &d) { return d.v1(); } +}; + +// specialization for 2nd field of a plain duo +template <typename A, typename B> +class DuoValue<2, UbDuo<A, B> > +{ +public: + static B& get(UbDuo<A, B> &d) { return d.v2(); } + static B const& get(UbDuo<A, B> const &d) { return d.v2(); } +}; + +// specialization for Nth field of recursive duo +template <int N, typename A, typename B, typename C> +struct DuoValue<N, UbDuo<A, UbDuo<B,C> > > +{ + static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefT get(UbDuo<A, UbDuo<B,C> > &d) + { + return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); + } + static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefConstT get(UbDuo<A, UbDuo<B,C> > const &d) + { + return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); + } +}; + +// specialization for 1st field of recursive duo +template <typename A, typename B, typename C> +class DuoValue<1, UbDuo<A, UbDuo<B,C> > > +{ +public: + static A& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v1(); } + static A const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v1(); } +}; + +// specialization for 2nd field of recursive duo +template <typename A, typename B, typename C> +class DuoValue<2, UbDuo<A, UbDuo<B,C> > > +{ +public: + static B& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v2().v1(); } + static B const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v2().v1(); } +}; + +//duo5.hpp +// return Nth value of variable duo +template <int N, typename A, typename B> +inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefT val(UbDuo<A, B>& d) +{ + return DuoValue<N, UbDuo<A, B> >::get(d); +} + +// return Nth value of constant duo +template <int N, typename A, typename B> +inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefConstT val(UbDuo<A, B> const& d) +{ + return DuoValue<N, UbDuo<A, B> >::get(d); +} + +//duo6.hpp +// partial specialization for UbDuo<> with only c1 field +template <typename A> +struct UbDuo<A,void> +{ +public: + typedef A T1; // type of first field + typedef void T2; // type of second field + enum { N = 1 }; // number of fields + +private: + T1 value1; // value of first field + +public: + // constructors + UbDuo() : value1() { } + UbDuo (T1 const & a) : value1(a) { } + + // field access + T1& v1() { return value1; } + T1 const& v1() const { return value1; } + + void v2() { } + void v2() const { } + +}; + +//tupel1.hpp +// type that represents unused type parameters +class UbNullT +{ +}; + +////////////////////////////////////////////////////////////////////////// +//! \brief A class implements a tuple +//! \details +//! usage: ...<BR> +//! Advanced UbTuple +//! Example: +//! create and use tuple with only c1 field +//! \code +//! UbTuple<int,int,int,int,int> t1; +//! val<1>(t1) += 42; +//! std::cout << t1.v1() << std::endl; +//! \endcode +//! create and use duo: +//! \code +//! UbTuple<bool,int> t2; +//! std::cout << val<1>(t2) << ", "; +//! std::cout << t2.v1() << std::endl; +//! \endcode +//! create and use triple: +//! \code +//! UbTuple<bool,int,double> t3; +//! val<1>(t3) = true; // new values via: val< pos >(triple) = ... +//! val<2>(t3) = 42; +//! val<3>(t3) = 0.2; +//! t3 = makeUbTuple(false, 23, 13.13); +//! +//! std::cout << val<1>(t3) << ", "; +//! std::cout << val<2>(t3) << ", "; +//! std::cout << val<3>(t3) << std::endl; +//! \endcode +//! create and use quadruple: +//! \code +//! UbType<bool,int,float,double> t4(true,42,13,1.95583); +//! std::cout << val<4>(t4) << std::endl; //<- option 2 (std) +//! std::cout << t4.v2().v2().v2() << std::endl; //<- option 2 +//! \endcode + +// UbTuple<> in general derives from UbTuple<> with c1 more UbNullT +template <typename P1, + typename P2 = UbNullT, + typename P3 = UbNullT, + typename P4 = UbNullT, + typename P5 = UbNullT, + typename P6 = UbNullT, + typename P7 = UbNullT, + typename P8 = UbNullT > +class UbTuple : public UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT> +{ +public: + typedef UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT> BaseT; + + // constructor: + UbTuple() {} + UbTuple( typename UbTypeOp<P1>::RefConstT a1, + typename UbTypeOp<P2>::RefConstT a2, + typename UbTypeOp<P3>::RefConstT a3 = UbNullT(), + typename UbTypeOp<P4>::RefConstT a4 = UbNullT(), + typename UbTypeOp<P5>::RefConstT a5 = UbNullT(), + typename UbTypeOp<P6>::RefConstT a6 = UbNullT(), + typename UbTypeOp<P7>::RefConstT a7 = UbNullT(), + typename UbTypeOp<P8>::RefConstT a8 = UbNullT() ) + : BaseT(a1, UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>(a2,a3,a4,a5,a6,a7,a8)) + { + } + + // for implicit type conversion during assignments + template <typename U1,typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8 > + UbTuple<P1,P2,P3,P4,P5,P6,P7,P8>& operator = ( const UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>& rhs) + { + this->BaseT::operator=( typename UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>::BaseT(rhs) ); + return *this; + } + +}; + +// specialization to end deriving recursion +template <typename P1, typename P2> +class UbTuple<P1,P2,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,P2> { +public: + typedef UbDuo<P1,P2> BaseT; + + // constructor: + UbTuple() {} + UbTuple( typename UbTypeOp<P1>::RefConstT a1, + typename UbTypeOp<P2>::RefConstT a2, + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) + : BaseT(a1, a2) + { + } + + // for implicit type conversion during assignments + template <typename U1,typename U2 > + UbTuple<P1,P2>& operator = ( const UbTuple<U1,U2>& rhs) + { + this->BaseT::operator=( typename UbTuple<U1,U2>::BaseT(rhs) ); + return *this; + } + +}; + +// specialization for singletons +template <typename P1> +class UbTuple<P1,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,void> +{ +public: + typedef UbDuo<P1,void> BaseT; + + // constructor: + UbTuple() {} + UbTuple( typename UbTypeOp<P1>::RefConstT a1, + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT(), + typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) + : BaseT(a1) + { + } + + // for implicit type conversion during assignments + template <typename U1 > + UbTuple<P1>& operator = ( const UbTuple<U1>& rhs) + { + this->v1() = rhs.v1(); + return *this; + } + +}; + +// convenience function for 1 argument +template <typename T1> +inline UbTuple<T1> makeUbTuple(T1 const &a1) +{ + return UbTuple<T1>(a1); +} + +// convenience function for 2 arguments +template <typename T1, typename T2> +inline UbTuple<T1,T2> makeUbTuple(T1 const &a1, T2 const &a2) +{ + return UbTuple<T1,T2>(a1,a2); +} + +// convenience function for 3 arguments +template <typename T1, typename T2, typename T3> +inline UbTuple<T1,T2,T3> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3) +{ + return UbTuple<T1,T2,T3>(a1,a2,a3); +} + +// convenience function for 4 arguments +template <typename T1, typename T2, typename T3, typename T4> +inline UbTuple<T1,T2,T3,T4> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4) +{ + return UbTuple<T1,T2,T3,T4>(a1,a2,a3,a4); +} + +// convenience function for 5 arguments +template <typename T1, typename T2, typename T3, typename T4, typename T5> +inline UbTuple<T1,T2,T3,T4,T5> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4,T5 const &a5) +{ + return UbTuple<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5); +} + +// convenience function for 6 arguments +template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> +inline UbTuple<T1,T2,T3,T4,T5,T6> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6) +{ + return UbTuple<T1,T2,T3,T4,T5,T6>(a1,a2,a3,a4,a5,a6); +} + +// convenience function for 7 arguments +template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> +inline UbTuple<T1,T2,T3,T4,T5,T6,T7> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7) +{ + return UbTuple<T1,T2,T3,T4,T5,T6,T7>(a1,a2,a3,a4,a5,a6,a7); +} + +// convenience function for 8 arguments +template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> +inline UbTuple<T1,T2,T3,T4,T5,T6,T7,T8> makeUbTuple(T1 const &a1, T2 const &a2,T3 const &a3, T4 const &a4,T5 const &a5, T6 const &a6,T7 const &a7, T8 const &a8 ) +{ + return UbTuple<T1,T2,T3,T4,T5,T6,T7,T8>(a1,a2,a3,a4,a5,a6,a7,a8); +} + +//some typedefs +typedef UbTuple<float,float> UbTupleFloat2; +typedef UbTuple<float,float,float> UbTupleFloat3; +typedef UbTuple<int,int> UbTupleInt2; +typedef UbTuple<int,int,int> UbTupleInt3; +typedef UbTuple<int,int,int,int> UbTupleInt4; +typedef UbTuple<int,int,int,int,int> UbTupleInt5; +typedef UbTuple<int,int,int,int,int,int> UbTupleInt6; +typedef UbTuple<int,int,int,int,int,int,int,int> UbTupleInt8; +typedef UbTuple<double,double> UbTupleDouble2; +typedef UbTuple<double,double,double> UbTupleDouble3; +typedef UbTuple<double,double,double,double> UbTupleDouble4; +typedef UbTuple<double,double,double,double,double,double> UbTupleDouble6; +typedef UbTuple<std::string,double,double> UbTupleStringDouble2; +typedef UbTuple<std::string,double,double,double> UbTupleStringDouble3; +typedef UbTuple<std::string,int,int,int> UbTupleStringInt3; +typedef UbTuple<short,short,short,short> UbTupleShort4; +typedef UbTuple<bool,bool,bool> UbTupleBool3; +typedef UbTuple<int,double,double> UbTupleIntDouble2; +typedef UbTuple<int, bool> UbTupleIntBool; + + +#endif //UBTUPLE_H diff --git a/VirtualFluidsBasics/basics/utilities/Vector3D.cpp b/VirtualFluidsBasics/basics/utilities/Vector3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b39ee8a410689d89bc41dfc2ed8291f11bd5bb1 --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/Vector3D.cpp @@ -0,0 +1,642 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbVector3D.cpp +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <basics/utilities/Vector3D.h> + +#include <cassert> +#include <sstream> + +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbInfinity.h> + + + +const Vector3D Vector3D::ZERO(0.0,0.0,0.0); +const Vector3D Vector3D::UNIT_X1(1.0,0.0,0.0); +const Vector3D Vector3D::UNIT_X2(0.0,1.0,0.0); +const Vector3D Vector3D::UNIT_X3(0.0,0.0,1.0); + +/*=======================================================*/ +Vector3D::Vector3D() +{ + m_afTuple[0] = 0.0; + m_afTuple[1] = 0.0; + m_afTuple[2] = 0.0; +} +/*=======================================================*/ +Vector3D::Vector3D(const double& fX, const double& fY, const double& fZ) +{ + m_afTuple[0] = fX; + m_afTuple[1] = fY; + m_afTuple[2] = fZ; +} +/*=======================================================*/ +Vector3D::Vector3D (const Vector3D& rkV) +{ + m_afTuple[0] = rkV.m_afTuple[0]; + m_afTuple[1] = rkV.m_afTuple[1]; + m_afTuple[2] = rkV.m_afTuple[2]; +} +/*=======================================================*/ +std::string Vector3D::toString() const +{ + std::stringstream os; + os<< "Vector3D["<<m_afTuple[0]<<","<<m_afTuple[1]<<","<<m_afTuple[2]<<"]"; + return os.str(); +} +/*=======================================================*/ +Vector3D::operator const double*() const +{ + return m_afTuple; +} +/*=======================================================*/ +Vector3D::operator double*() +{ + return m_afTuple; +} +/*=======================================================*/ +double Vector3D::operator[](const int& i) const +{ + assert( i >= 0 && i <= 2 ); + return m_afTuple[i]; +} +/*=======================================================*/ +double& Vector3D::operator[](const int& i) +{ + assert( i >= 0 && i <= 2 ); + return m_afTuple[i]; +} +/*=======================================================*/ +double Vector3D::X1() const +{ + return m_afTuple[0]; +} +/*=======================================================*/ +double& Vector3D::X1() +{ + return m_afTuple[0]; +} +/*=======================================================*/ +double Vector3D::X2() const +{ + return m_afTuple[1]; +} +/*=======================================================*/ +double& Vector3D::X2() +{ + return m_afTuple[1]; +} +/*=======================================================*/ +double Vector3D::X3() const +{ + return m_afTuple[2]; +} +/*=======================================================*/ +double& Vector3D::X3() +{ + return m_afTuple[2]; +} +/*=======================================================*/ +Vector3D& Vector3D::operator=(const Vector3D& rkV) +{ + m_afTuple[0] = rkV.m_afTuple[0]; + m_afTuple[1] = rkV.m_afTuple[1]; + m_afTuple[2] = rkV.m_afTuple[2]; + return *this; +} +/*=======================================================*/ +int Vector3D::CompareArrays(const Vector3D& rkV) const +{ + return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(double)); +} +/*=======================================================*/ +bool Vector3D::operator==(const Vector3D& rkV) const +{ + return CompareArrays(rkV) == 0; +} +/*=======================================================*/ +bool Vector3D::operator!=(const Vector3D& rkV) const +{ + return CompareArrays(rkV) != 0; +} +/*=======================================================*/ +bool Vector3D::operator<(const Vector3D& rkV) const +{ + return CompareArrays(rkV) < 0; +} +/*=======================================================*/ +bool Vector3D::operator<=(const Vector3D& rkV) const +{ + return CompareArrays(rkV) <= 0; +} +/*=======================================================*/ +bool Vector3D::operator> (const Vector3D& rkV) const +{ + return CompareArrays(rkV) > 0; +} +/*=======================================================*/ +bool Vector3D::operator>=(const Vector3D& rkV) const +{ + return CompareArrays(rkV) >= 0; +} +/*=======================================================*/ +Vector3D Vector3D::operator+(const Vector3D& rkV) const +{ + return Vector3D( m_afTuple[0]+rkV.m_afTuple[0], + m_afTuple[1]+rkV.m_afTuple[1], + m_afTuple[2]+rkV.m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D Vector3D::Add(Vector3D& vector) +{ + return Vector3D( m_afTuple[0]+vector.m_afTuple[0], + m_afTuple[1]+vector.m_afTuple[1], + m_afTuple[2]+vector.m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D Vector3D::operator- (const Vector3D& rkV) const +{ + return Vector3D( m_afTuple[0]-rkV.m_afTuple[0], + m_afTuple[1]-rkV.m_afTuple[1], + m_afTuple[2]-rkV.m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D Vector3D::Subtract(Vector3D& vector) +{ + return Vector3D( m_afTuple[0]-vector.m_afTuple[0], + m_afTuple[1]-vector.m_afTuple[1], + m_afTuple[2]-vector.m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D Vector3D::operator*(const double& fScalar) const +{ + return Vector3D( fScalar*m_afTuple[0], + fScalar*m_afTuple[1], + fScalar*m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D Vector3D::operator/(const double& fScalar) const +{ + Vector3D kQuot; + + if ( fScalar != 0.0 ) + { + double fInvScalar = 1.0/fScalar; + kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0]; + kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1]; + kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2]; + } + else + { + kQuot.m_afTuple[0] = Ub::inf; + kQuot.m_afTuple[1] = Ub::inf; + kQuot.m_afTuple[2] = Ub::inf; + } + + return kQuot; +} +/*=======================================================*/ +Vector3D Vector3D::operator-() const +{ + return Vector3D( -m_afTuple[0], + -m_afTuple[1], + -m_afTuple[2] ); +} +/*=======================================================*/ +Vector3D& Vector3D::operator+=(const Vector3D& rkV) +{ + m_afTuple[0] += rkV.m_afTuple[0]; + m_afTuple[1] += rkV.m_afTuple[1]; + m_afTuple[2] += rkV.m_afTuple[2]; + return *this; +} +/*=======================================================*/ +Vector3D& Vector3D::operator-=(const Vector3D& rkV) +{ + m_afTuple[0] -= rkV.m_afTuple[0]; + m_afTuple[1] -= rkV.m_afTuple[1]; + m_afTuple[2] -= rkV.m_afTuple[2]; + return *this; +} +/*=======================================================*/ +Vector3D& Vector3D::operator*=(const double& fScalar) +{ + m_afTuple[0] *= fScalar; + m_afTuple[1] *= fScalar; + m_afTuple[2] *= fScalar; + return *this; +} +/*=======================================================*/ +Vector3D& Vector3D::operator/=(const double& fScalar) +{ + if ( !UbMath::zero(fScalar) ) + { + double fInvScalar = 1.0/fScalar; + m_afTuple[0] *= fInvScalar; + m_afTuple[1] *= fInvScalar; + m_afTuple[2] *= fInvScalar; + } + else + { + m_afTuple[0] = Ub::inf; + m_afTuple[1] = Ub::inf; + m_afTuple[2] = Ub::inf; + } + + return *this; +} +/*=======================================================*/ +Vector3D Vector3D::Scale(const double& x) +{ + Vector3D PointA(0.0,0.0,0.0); + PointA.m_afTuple[0] = x * m_afTuple[0]; + PointA.m_afTuple[1] = x * m_afTuple[1]; + PointA.m_afTuple[2] = x * m_afTuple[2]; + return PointA; +} +/*=======================================================*/ +double Vector3D::Length() const +{ + return std::sqrt( m_afTuple[0]*m_afTuple[0] + + m_afTuple[1]*m_afTuple[1] + + m_afTuple[2]*m_afTuple[2] ); +} +/*=======================================================*/ +double Vector3D::SquaredLength() const +{ + return m_afTuple[0]*m_afTuple[0] + + m_afTuple[1]*m_afTuple[1] + + m_afTuple[2]*m_afTuple[2]; +} +/*=======================================================*/ +double Vector3D::Dot(const Vector3D& rkV) const +{ + return m_afTuple[0]*rkV.m_afTuple[0] + + m_afTuple[1]*rkV.m_afTuple[1] + + m_afTuple[2]*rkV.m_afTuple[2]; +} +/*=======================================================*/ +double Vector3D::Normalize() +{ + double fLength = Length(); + + if( !UbMath::zero(fLength) ) + { + double fInvLength = 1.0/fLength; + m_afTuple[0] *= fInvLength; + m_afTuple[1] *= fInvLength; + m_afTuple[2] *= fInvLength; + } + else + { + fLength = 0.0; + m_afTuple[0] = 0.0; + m_afTuple[1] = 0.0; + m_afTuple[2] = 0.0; + } + + return fLength; +} +/*=======================================================*/ +Vector3D Vector3D::Cross(const Vector3D& rkV) const +{ + return Vector3D( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1], + m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2], + m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] ); +} +/*=======================================================*/ +Vector3D Vector3D::UnitCross(const Vector3D& rkV) const +{ + Vector3D kCross( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1], + m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2], + m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] ); + kCross.Normalize(); + return kCross; +} +/*=======================================================*/ +void Vector3D::GetBarycentrics(const Vector3D& rkV0,const Vector3D& rkV1, const Vector3D& rkV2,const Vector3D& rkV3, double afBary[4]) const +{ + // compute the vectors relative to V3 of the tetrahedron + Vector3D akDiff[4] = { rkV0 - rkV3, + rkV1 - rkV3, + rkV2 - rkV3, + *this - rkV3 }; + + // If the vertices have large magnitude, the linear system of + // equations for computing barycentric coordinates can be + // ill-conditioned. To avoid this, uniformly scale the tetrahedron + // edges to be of order 1. The scaling of all differences does not + // change the barycentric coordinates. + double fMax = 0.0,fValue=0.0; + for(int i=0; i<3; i++) + for (int j=0; j<3; j++) + { + fValue = std::fabs(akDiff[i][j]); + if ( fValue > fMax ) fMax = fValue; + } + + // scale down only large data + if(UbMath::greater(fMax,1.0) ) + { + double fInvMax = ((double)1.0)/fMax; + for( int i=0; i<4; i++) + akDiff[i] *= fInvMax; + } + + double fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2])); + Vector3D kE1cE2 = akDiff[1].Cross(akDiff[2]); + Vector3D kE2cE0 = akDiff[2].Cross(akDiff[0]); + Vector3D kE0cE1 = akDiff[0].Cross(akDiff[1]); + + if( !UbMath::zero( fDet ) ) + { + double fInvDet = 1.0/fDet; + afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet; + afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet; + afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet; + afBary[3] = 1.0 - afBary[0] - afBary[1] - afBary[2]; + } + else + { + // The tetrahedron is potentially flat. Determine the face of + // maximum area and compute barycentric coordinates with respect + // to that face. + Vector3D kE02 = rkV0 - rkV2; + Vector3D kE12 = rkV1 - rkV2; + Vector3D kE02cE12 = kE02.Cross(kE12); + double fMaxSqrArea = kE02cE12.SquaredLength(); + int iMaxIndex = 3; + double fSqrArea = kE0cE1.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 0; + fMaxSqrArea = fSqrArea; + } + fSqrArea = kE1cE2.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 1; + fMaxSqrArea = fSqrArea; + } + fSqrArea = kE2cE0.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 2; + fMaxSqrArea = fSqrArea; + } + + if (UbMath::greater(fMaxSqrArea,0.0) ) + { + double fInvSqrArea = 1.0/fMaxSqrArea; + Vector3D kTmp; + if( iMaxIndex==0 ) + { + kTmp = akDiff[3].Cross(akDiff[1]); + afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea; + kTmp = akDiff[0].Cross(akDiff[3]); + afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea; + afBary[2] = 0.0; + afBary[3] = 1.0 - afBary[0] - afBary[1]; + } + else if( iMaxIndex == 1 ) + { + afBary[0] = 0.0; + kTmp = akDiff[3].Cross(akDiff[2]); + afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea; + kTmp = akDiff[1].Cross(akDiff[3]); + afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea; + afBary[3] = 1.0 - afBary[1] - afBary[2]; + } + else if( iMaxIndex == 2 ) + { + kTmp = akDiff[2].Cross(akDiff[3]); + afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea; + afBary[1] = 0.0; + kTmp = akDiff[3].Cross(akDiff[0]); + afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea; + afBary[3] = 1.0 - afBary[0] - afBary[2]; + } + else + { + akDiff[3] = *this - rkV2; + kTmp = akDiff[3].Cross(kE12); + afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea; + kTmp = kE02.Cross(akDiff[3]); + afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea; + afBary[2] = 1.0 - afBary[0] - afBary[1]; + afBary[3] = 0.0; + } + } + else + { + // The tetrahedron is potentially a sliver. Determine the edge of + // maximum length and compute barycentric coordinates with respect + // to that edge. + double fMaxSqrLength = akDiff[0].SquaredLength(); + iMaxIndex = 0; // <V0,V3> + double fSqrLength = akDiff[1].SquaredLength(); + + if( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 1; // <V1,V3> + fMaxSqrLength = fSqrLength; + } + fSqrLength = akDiff[2].SquaredLength(); + + if( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 2; // <V2,V3> + fMaxSqrLength = fSqrLength; + } + fSqrLength = kE02.SquaredLength(); + + if( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 3; // <V0,V2> + fMaxSqrLength = fSqrLength; + } + fSqrLength = kE12.SquaredLength(); + + if( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 4; // <V1,V2> + fMaxSqrLength = fSqrLength; + } + + Vector3D kE01 = rkV0 - rkV1; + fSqrLength = kE01.SquaredLength(); + + if( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 5; // <V0,V1> + fMaxSqrLength = fSqrLength; + } + + if(UbMath::greater(fMaxSqrLength, 0.0) ) + { + double fInvSqrLength = 1.0/fMaxSqrLength; + if( iMaxIndex == 0 ) + { + // P-V3 = t*(V0-V3) + afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength; + afBary[1] = 0.0; + afBary[2] = 0.0; + afBary[3] = 1.0 - afBary[0]; + } + else if( iMaxIndex == 1 ) + { + // P-V3 = t*(V1-V3) + afBary[0] = 0.0; + afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength; + afBary[2] = 0.0; + afBary[3] = 1.0 - afBary[1]; + } + else if( iMaxIndex == 2 ) + { + // P-V3 = t*(V2-V3) + afBary[0] = 0.0; + afBary[1] = 0.0; + afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength; + afBary[3] = 1.0 - afBary[2]; + } + else if( iMaxIndex == 3 ) + { + // P-V2 = t*(V0-V2) + akDiff[3] = *this - rkV2; + afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength; + afBary[1] = 0.0; + afBary[2] = 1.0 - afBary[0]; + afBary[3] = 0.0; + } + else if( iMaxIndex == 4 ) + { + // P-V2 = t*(V1-V2) + akDiff[3] = *this - rkV2; + afBary[0] = 0.0; + afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength; + afBary[2] = 1.0 - afBary[1]; + afBary[3] = 0.0; + } + else + { + // P-V1 = t*(V0-V1) + akDiff[3] = *this - rkV1; + afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength; + afBary[1] = 1.0 - afBary[0]; + afBary[2] = 0.0; + afBary[3] = 0.0; + } + } + else + { + // tetrahedron is a nearly a point, just return equal weights + afBary[0] = 0.25; + afBary[1] = afBary[0]; + afBary[2] = afBary[0]; + afBary[3] = afBary[0]; + } + } + } +} +/*=======================================================*/ +void Vector3D::Orthonormalize(Vector3D& rkU, Vector3D& rkV, Vector3D& rkW) +{ + // If the input vectors are v0, v1, and v2, then the Gram-Schmidt + // orthonormalization produces vectors u0, u1, and u2 as follows, + // + // u0 = v0/|v0| + // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| + // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| + // + // where |A| indicates length of vector A and A*B indicates dot + // product of vectors A and B. + + // compute u0 + rkU.Normalize(); + + // compute u1 + double fDot0 = rkU.Dot(rkV); + rkV -= fDot0*rkU; + rkV.Normalize(); + + // compute u2 + double fDot1 = rkV.Dot(rkW); + fDot0 = rkU.Dot(rkW); + rkW -= fDot0*rkU + fDot1*rkV; + rkW.Normalize(); +} +/*=======================================================*/ +void Vector3D::Orthonormalize(Vector3D* akV) +{ + Orthonormalize(akV[0],akV[1],akV[2]); +} +/*=======================================================*/ +void Vector3D::GenerateOrthonormalBasis(Vector3D& rkU, Vector3D& rkV,Vector3D& rkW, bool bUnitLengthW) +{ + if ( !bUnitLengthW ) + rkW.Normalize(); + + double fInvLength; + + if (UbMath::greaterEqual( std::fabs(rkW.m_afTuple[0]),std::fabs(rkW.m_afTuple[1]) ) ) + { + // W.x or W.z is the largest magnitude component, swap them + fInvLength = UbMath::invSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] + rkW.m_afTuple[2]*rkW.m_afTuple[2]); + rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength; + rkU.m_afTuple[1] = (double)0.0; + rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength; + } + else + { + // W.y or W.z is the largest magnitude component, swap them + fInvLength = UbMath::invSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] + rkW.m_afTuple[2]*rkW.m_afTuple[2]); + rkU.m_afTuple[0] = (double)0.0; + rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength; + rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength; + } + + rkV = rkW.Cross(rkU); +} +/*=======================================================*/ +//globaler operator* +Vector3D operator*(const double& fScalar, const Vector3D& rkV) +{ + return Vector3D( fScalar*rkV[0], + fScalar*rkV[1], + fScalar*rkV[2] ); +} +/*=======================================================*/ +std::ostream& operator<< (std::ostream& os, const Vector3D& rkV) +{ + os<<rkV.toString(); + return os; +} diff --git a/VirtualFluidsBasics/basics/utilities/Vector3D.h b/VirtualFluidsBasics/basics/utilities/Vector3D.h new file mode 100644 index 0000000000000000000000000000000000000000..1e1d5178bdeca3a7d61595e54d1c999941a3ecdd --- /dev/null +++ b/VirtualFluidsBasics/basics/utilities/Vector3D.h @@ -0,0 +1,136 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file UbVector3D.h +//! \ingroup utilities +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef VECTOR_3D_H +#define VECTOR_3D_H + +#include <string> + + class Vector3D + { + public: + // construction + Vector3D(); + Vector3D(const double& fX1, const double& fX2, const double& fX3); + Vector3D(const Vector3D& rkV); + + std::string toString() const; + + // coordinate access + operator const double*() const; + operator double*(); + double operator[](const int& i) const; + double& operator[](const int& i); + double X1() const; + double& X1(); + double X2() const; + double& X2(); + double X3() const; + double& X3(); + + // assignment + Vector3D& operator=(const Vector3D& rkV); + + // comparison + bool operator==(const Vector3D& rkV) const; + bool operator!=(const Vector3D& rkV) const; + bool operator< (const Vector3D& rkV) const; + bool operator<=(const Vector3D& rkV) const; + bool operator> (const Vector3D& rkV) const; + bool operator>=(const Vector3D& rkV) const; + + // arithmetic operations + Vector3D operator+(const Vector3D& rkV) const; + Vector3D operator-(const Vector3D& rkV) const; + Vector3D operator*(const double& fScalar) const; + Vector3D operator/(const double& fScalar) const; + Vector3D operator-() const; + + // arithmetic updates + Vector3D& operator+= (const Vector3D& rkV); + Vector3D& operator-= (const Vector3D& rkV); + Vector3D& operator*= (const double& fScalar); + Vector3D& operator/= (const double& fScalar); + + Vector3D Add(Vector3D& vector); + Vector3D Subtract(Vector3D& vector); + Vector3D Scale(const double& x); + + // vector operations + double Length () const; + double SquaredLength () const; + double Dot (const Vector3D& rkV) const; + double Normalize (); + + // The cross products are computed using the right-handed rule. Be aware + // that some graphics APIs use a left-handed rule. If you have to compute + // a cross product with these functions and send the result to the API + // that expects left-handed, you will need to change sign on the vector + // (replace each component value c by -c). + Vector3D Cross (const Vector3D& rkV) const; + Vector3D UnitCross (const Vector3D& rkV) const; + + // Compute the barycentric coordinates of the point with respect to the + // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where + // b0 + b1 + b2 + b3 = 1. + void GetBarycentrics (const Vector3D& rkV0, const Vector3D& rkV1, const Vector3D& rkV2, const Vector3D& rkV3, double afBary[4]) const; + + // Gram-Schmidt orthonormalization. Take linearly independent vectors + // U, V, and W and compute an orthonormal set (unit length, mutually + // perpendicular). + static void Orthonormalize (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW); + static void Orthonormalize (Vector3D* akV); + + // Input W must be initialized to a nonzero vector, output is {U,V,W}, + // an orthonormal basis. A hint is provided about whether or not W + // is already unit length. + static void GenerateOrthonormalBasis (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW, bool bUnitLengthW); + + // special vectors + static const Vector3D ZERO; + static const Vector3D UNIT_X1; + static const Vector3D UNIT_X2; + static const Vector3D UNIT_X3; + + protected: + // support for comparisons + int CompareArrays (const Vector3D& rkV) const; + + double m_afTuple[3]; + }; + + //globaler multiplaktor mit skalar + Vector3D operator*(const double& fScalar, const Vector3D& rkV); + std::ostream& operator<<(std::ostream& os, const Vector3D& rkV); + + +#endif diff --git a/VirtualFluidsBasics/basics/writer/CMakePackage.txt b/VirtualFluidsBasics/basics/writer/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ef17942b856d69df194c11f63050e950564927b --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/CMakePackage.txt @@ -0,0 +1,3 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) + diff --git a/VirtualFluidsBasics/basics/writer/WbWriter.h b/VirtualFluidsBasics/basics/writer/WbWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..c6793c5ae9366f48b7b636403b929b411561253b --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/WbWriter.h @@ -0,0 +1,114 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WbWriter.h +//! \ingroup writer +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef WBWRITER_H +#define WBWRITER_H + +#include <vector> +#include <string> +#include <fstream> +#include <sstream> +#include <iostream> +#include <map> + + +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbTuple.h> + +class WbWriter +{ +public: + ////////////////////////////////////////////////////////////////////////// + virtual ~WbWriter() + { + + } + + ////////////////////////////////////////////////////////////////////////// + //rein virtuelle Methoden + virtual std::string getFileExtension() = 0; + + ////////////////////////////////////////////////////////////////////////// + //nodes + virtual std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + ////////////////////////////////////////////////////////////////////////// + //lines + // 0 ---- 1 + //nodenumbering must start with 0! + virtual std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + ////////////////////////////////////////////////////////////////////////// + //triangles + //cell numbering: + // 2 + // + // 0 === 1 + //nodenumbering must start with 0! + virtual std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + ////////////////////////////////////////////////////////////////////////// + //quads + //cell numbering: + // 3---2 + // | | + // 0---1 + //nodenumbering must start with 0! + virtual std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, + std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, std::vector< std::vector< double > >&celldata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + ////////////////////////////////////////////////////////////////////////// + //octs + // 7 ---- 6 + // /| /| + // 4 +--- 5 | + // | | | | + // | 3 ---+ 2 + // |/ |/ + // 0 ---- 1 + virtual std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + +private: + +}; + +#endif //WBWRITER_H diff --git a/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.cpp b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42b7defd6b5dd7616dc9aeb0e97dd884d18d6db1 --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.cpp @@ -0,0 +1,1221 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WbWriterVtkXmlASCII.cpp +//! \ingroup writer +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <basics/writer/WbWriterVtkXmlASCII.h> +#include <basics/utilities/UbLogger.h> +#include <cstring> +#include <limits> + +using namespace std; + +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::pvdEndTag =" </Collection>\n</VTKFile>"; +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups) +{ + std::string vtkfilename=filename+".pvd"; + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + std::string endian; + if(UbSystem::isLittleEndian()) endian = "LittleEndian"; + else endian = "BigEndian"; + out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >\n"; + out<<" <Collection>"<<endl; + + int group = 0, part=0; + for(std::size_t i=0; i<filenames.size(); i++) + { + out<<" <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>\n"; + if(sepGroups) group++; + else part++; + } + out<<pvdEndTag; + out.close(); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups) +{ + std::string vtkfilename=filename; + std::fstream test(vtkfilename.c_str(), ios::in); + if(!test) + { + test.clear(); + vtkfilename += ".pvd"; + test.open(vtkfilename.c_str(), ios::in); + if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups); + } + + std::fstream out(vtkfilename.c_str(), ios::in | ios::out); + out.seekp(-(int)pvdEndTag.size()-1, ios_base::end); + + int group = 0; + for(std::size_t i=0; i<filenames.size(); i++) + { + out<<" <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>\n"; + if(sepGroups) group++; + } + out<<pvdEndTag; + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames) +{ + string vtkfilename=filename+".pvtu"; + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + //VTK FILE + out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n"; + out<<" <PUnstructuredGrid GhostLevel=\"0\">\n"; + out<<" <PPoints>\n"; + out<<" <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n"; + out<<" </PPoints>\n"; + out<<" <PPointData>\n"; + for(size_t s=0; s<pointDataNames.size(); s++) + out<< " <PDataArray type=\"Float64\" Name=\""<< pointDataNames[s] <<"\"/>\n"; + out<<" </PPointData>\n"; + if (cellDataNames.size() > 0) + { + out<<" <PCellData>\n"; + for(size_t s=0; s<cellDataNames.size(); s++) + out<< " <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n"; + out<<" </PCellData>\n"; + } + + for(size_t s=0; s<pieceSources.size(); s++) + out<<" <Piece Source=\""<<pieceSources[s]<<"\"/>\n"; + out<<" </PUnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"; + for(int c=1; c<nofCells+1; c++) + out<<c*4<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + + for(int c=0; c<nofCells; c++) + out<<"8 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*4<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"8 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write data section + out<<" <PointData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end"); + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*4<<" " ; + + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"8 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write data section + out<<" <CellData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)celldata[s].size(); d++) + out<<celldata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </CellData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + + out.close(); + + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, + vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, + vector< vector< double > >& celldata ) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*4<<" " ; + + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"8 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write PointData section + out<<" <PointData Scalars=\"PScalars\"> \n"; + for(int s=0; s<(int)nodedatanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + + //write celldata section + out<<" <CellData Scalars=\"CScalars\"> \n"; + for(int s=0; s<(int)celldatanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)celldata[s].size(); d++) + out<<celldata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </CellData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofLines = (int)lines.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofLines<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"; + + for(int c=0; c<nofLines; c++) + out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"; + for(int c=1; c<=nofLines; c++) + out<<c*2<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + + for(int c=0; c<nofLines; c++) + out<<"3 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofLines = (int)lines.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofLines<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"; + + for(int c=0; c<nofLines; c++) + out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"; + for(int c=1; c<=nofLines; c++) + out<<c*2<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + + for(int c=0; c<nofLines; c++) + out<<"3 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + + //write data section + out<<" <PointData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofTriangles= (int)triangles.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofTriangles<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"; + + for(int c=0; c<nofTriangles; c++) + out<< val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"; + for(int c=1; c<nofTriangles+1; c++) + out<<c*3<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + + for(int c=0; c<nofTriangles; c++) + out<<"5 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" "<< val<2>(cells[c]) <<" "<< val<3>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*3<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"5 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write data section + out<<" <PointData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" " + << val<5>(cells[c]) <<" " + << val<6>(cells[c]) <<" " + << val<8>(cells[c]) <<" " + << val<7>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*8<<" " ; + + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"11 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + + //write data section + out<<" <CellData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)celldata[s].size(); d++) + out<<celldata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </CellData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<<val<1>(nodes[n])<<" "<<val<2>(nodes[n])<<" "<<val<3>(nodes[n])<<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" " + << val<5>(cells[c]) <<" " + << val<6>(cells[c]) <<" " + << val<8>(cells[c]) <<" " + << val<7>(cells[c]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*8<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"11 "; + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write PointData section + out<<" <PointData Scalars=\"PScalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"ascii\">"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + { + //out<<base64_encode((unsigned char*)(&nodedata[s][d]),sizeof(float)); + //out.write((char*)&nodedata[s][d],sizeof(float)); + out<<nodedata[s][d]<<" "; + } + out<<"</DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<< val<1>(cells[c]) <<" " + << val<2>(cells[c]) <<" " + << val<4>(cells[c]) <<" " + << val<3>(cells[c]) <<" " + << val<5>(cells[c]) <<" " + << val<6>(cells[c]) <<" " + << val<8>(cells[c]) <<" " + << val<7>(cells[c]) <<" "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofCells+1; c++) + out<<c*8<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + + for(int c=0; c<nofCells; c++) + out<<"11 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +std::string WbWriterVtkXmlASCII::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"; + for(int n=0; n<nofNodes; n++) + out<< n << " "; + out<<"\n"; + + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"; + for(int n=1; n<=nofNodes; n++) + out << n << " "; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + + for(int n=0; n<nofNodes; n++) + out<<"1 "; + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Cells>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +std::string WbWriterVtkXmlASCII::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofNodes; c++) + out << c <<" "; + out<<"\n"; + + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofNodes+1; c++) + out<<c<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + for(int c=0; c<nofNodes; c++) + out<<"1 "; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write data section + out<<" <PointData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} + +////////////////////////////////////////////////////////////////////////// +std::string WbWriterVtkXmlASCII::writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) +{ + string vtkfilename=filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start"); + + std::ofstream out(vtkfilename.c_str()); + out.precision (std::numeric_limits<double>::digits10 + 1); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + + //VTK FILE + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\"> \n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n "; + for(int n=0; n<nofNodes; n++) + out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" "; + + out<<"\n"; + out<<" </DataArray>\n"; + out<<" </Points>\n"; + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n "; + + for(int c=0; c<nofNodes; c++) + out << c <<" "; + out<<"\n"; + + out<<" </DataArray>\n"; + out<<" <DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\">\n "; + for(int c=1; c<nofNodes+1; c++) + out<<c<<" " ; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n "; + for(int c=0; c<nofNodes; c++) + out<<"1 "; + + out<<"\n"; + out<<" </DataArray>\n"; + + out<<" </Cells>\n"; + + //write data section + out<<" <PointData Scalars=\"Scalars\"> \n"; + for(int s=0; s<(int)datanames.size(); ++s) + { + out<< " <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n"; + + for(int d=0; d<(int)nodedata[s].size(); d++) + out<<nodedata[s][d]<<" "; + + out<<"\n </DataArray>\n"; + } + out<<" </PointData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} diff --git a/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.h b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.h new file mode 100644 index 0000000000000000000000000000000000000000..ea76ed3b9c56730934fb8d1f673a05bc23740361 --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlASCII.h @@ -0,0 +1,122 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WbWriterVtkXmlASCII.h +//! \ingroup writer +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef WBWRITERVTKXMLASCII_H +#define WBWRITERVTKXMLASCII_H + +#include <string> + +#include <basics/writer/WbWriter.h> + +class WbWriterVtkXmlASCII : public WbWriter +{ +public: + static WbWriterVtkXmlASCII* getInstance() + { + static WbWriterVtkXmlASCII instance; + return &instance; + } +private: + WbWriterVtkXmlASCII() : WbWriter() + { + if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char type mismatch"); + if(sizeof(int) !=4) throw UbException(UB_EXARGS,"error int type mismatch"); + if(sizeof(float) !=4) throw UbException(UB_EXARGS,"error float type mismatch"); + } + WbWriterVtkXmlASCII( const WbWriterVtkXmlASCII& ); //no copy allowed + const WbWriterVtkXmlASCII& operator=( const WbWriterVtkXmlASCII& ); //no copy allowed + + static std::string pvdEndTag; + +public: + std::string getFileExtension() { return ".ascii.vtu"; } + + //write a metafile + std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timesteps, const bool& sepGroups);//std::vector<double>& groups, std::vector<double>& parts); + std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups); + std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames); + + ////////////////////////////////////////////////////////////////////////// + //nodes + std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes); + std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata); + std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //lines + // 0 ---- 1 + //nodenumbering must start with 0! + std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines); + std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //triangles + // 2 + // + // 0---1 + //nodenumbering must start with 0! + std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles); + std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //2D + //cell numbering: + // 3---2 + // | | + // 0---1 + //nodenumbering must start with 0! + + std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells); + std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata); + std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, + std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, + std::vector< std::vector< double > >& celldata ); + + ////////////////////////////////////////////////////////////////////////// + //octs + // 7 ---- 6 + // /| /| + // 4 +--- 5 | + // | | | | + // | 3 ---+ 2 + // |/ |/ + // 0 ---- 1 + std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells); + std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata); + std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + +private: + +}; + +#endif //WBWRITERVTKXMLASCII_H diff --git a/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.cpp b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67bd1f56397d6993e54333a07adb6867e2f6f196 --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.cpp @@ -0,0 +1,1618 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WbWriterVtkXmlBinary.cpp +//! \ingroup writer +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <basics/writer/WbWriterVtkXmlBinary.h> +#include <basics/writer/WbWriterVtkXmlASCII.h> +#include <basics/utilities/UbLogger.h> +#include <cstring> + +using namespace std; + +/*===============================================================================*/ +string WbWriterVtkXmlBinary::pvdEndTag =" </Collection>\n</VTKFile>"; +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups) +{ + string vtkfilename=filename+".pvd"; + ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + string endian; + if(UbSystem::isLittleEndian()) endian = "LittleEndian"; + else endian = "BigEndian"; + out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >"<<endl; + out<<" <Collection>"<<endl; + + int group = 0, part=0; + for(size_t i=0; i<filenames.size(); i++) + { + out<<" <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>"<<endl; + if(sepGroups) group++; + else part++; + } + out<<pvdEndTag; + out.close(); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::addFilesToCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups) +{ + string vtkfilename=filename; + fstream test(vtkfilename.c_str(), ios::in); + if(!test) + { + test.clear(); + vtkfilename += ".pvd"; + test.open(vtkfilename.c_str(), ios::in); + if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups); + } + + fstream out(vtkfilename.c_str(), ios::in | ios::out); + out.seekp(-(int)pvdEndTag.size()-1, ios_base::end); + + int group = 0; + for(size_t i=0; i<filenames.size(); i++) + { + out<<" <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>"<<endl; + if(sepGroups) group++; + } + out<<pvdEndTag; + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames) +{ + string vtkfilename=filename+".pvtu"; + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str()); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + //VTK FILE + out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">"<<"\n"; + out<<" <PUnstructuredGrid GhostLevel=\"0\">"<<"\n"; + out<<" <PPoints>\n"; + out<<" <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n"; + out<<" </PPoints>\n"; + out<<" <PPointData>\n"; + for(size_t s=0; s<pointDataNames.size(); s++) + out<< " <PDataArray type=\"Float32\" Name=\""<< pointDataNames[s] <<"\"/>\n"; + out<<" </PPointData>\n"; + if (cellDataNames.size() > 0) + { + out<<" <PCellData>\n"; + for(size_t s=0; s<cellDataNames.size(); s++) + out<< " <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n"; + out<<" </PCellData>\n"; + } + + for(size_t s=0; s<pieceSources.size(); s++) + out<<" <Piece Source=\""<<pieceSources[s]<<"\"/>\n"; + out<<" </PUnstructuredGrid>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)lines.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 2 /*nodes per line */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per line */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of line */ * nofCells * sizeof(unsigned char); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(lines[c]), sizeof(int) ); + out.write( (char*)&val<2>(lines[c]), sizeof(int) ); + + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 2 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 3; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +std::string WbWriterVtkXmlBinary::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)lines.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 2 /*nodes per line */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per line */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of line */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </PointData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(lines[c]), sizeof(int) ); + out.write( (char*)&val<2>(lines[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 3 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 5; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + float tmp = (float)nodedata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; + +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + + int nofNodes = (int)nodes.size(); + int nofCells = (int)triangles.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 - coord */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 3 /*nodes per triangle */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per triangle */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of triangle */ * nofCells * sizeof(unsigned char); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(triangles[c]), sizeof(int) ); + out.write( (char*)&val<2>(triangles[c]), sizeof(int) ); + out.write( (char*)&val<3>(triangles[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 3 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 5; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out<<flush; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeTrianglesWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt3 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 3 /*nodes per tri */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per tri */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of tri */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </PointData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 3 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 5; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + float tmp = (float)nodedata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 4 /*nodes per quad */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per quad */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of quad */ * nofCells * sizeof(unsigned char); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 4 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 8; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out<<flush; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 4 /*nodes per quad */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per quad */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of quad */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </PointData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 4 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 8; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + float tmp = (float)nodedata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 4 /*nodes per quad */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per quad */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of quad */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofCells * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <CellData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </CellData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 4 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 8; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<celldata[s].size(); ++d) + { + //loake kopie machen, da in celldata "doubles" sind + float tmp = (float)celldata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + + out<<"\n</AppendedData>\n"; + + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, + vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, + vector< vector< double > >& celldata ) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 4 /*nodes per quad */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per quad */ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of quad */ * nofCells * sizeof(unsigned char); + int bytesScalarDataPoint = 1 /*scalar */ * nofNodes * sizeof(float); + int bytesScalarDataCell = 1 /*scalar */ * nofCells * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + // Point DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<nodedatanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarDataPoint); + } + out<<" </PointData>\n"; + + + // Cell DATA SECTION + out<<" <CellData>\n"; + for(size_t s=0; s<celldatanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarDataCell); + } + out<<" </CellData>\n"; + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 4 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 8; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //Point DATA SECTION + //scalarData + for(size_t s=0; s<nodedatanames.size(); ++s) + { + out.write((char*)&bytesScalarDataPoint,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + float tmp = (float)nodedata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + //Cell DATA SECTION + //scalarData + for(size_t s=0; s<celldatanames.size(); ++s) + { + out.write((char*)&bytesScalarDataCell,bytesPerByteVal); + for(size_t d=0; d<celldata[s].size(); ++d) + { + //loake kopie machen, da in celldata "doubles" sind + float tmp = (float)celldata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per oct*/ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of oct */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofCells * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <CellData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </CellData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + out.write( (char*)&val<5>(cells[c]), sizeof(int) ); + out.write( (char*)&val<6>(cells[c]), sizeof(int) ); + out.write( (char*)&val<8>(cells[c]), sizeof(int) ); + out.write( (char*)&val<7>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 8 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 11; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<celldata[s].size(); ++d) + { + //loake kopie machen, da in celldata "doubles" sind + float tmp = (float)celldata[s][d]; + out.write((char*)&tmp,sizeof(float)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per oct*/ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of oct */ * nofCells * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(double); + + unsigned long long offset = 0; + //VTK FILE + out<<"<?xml version=\"2.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </PointData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + out.write( (char*)&val<5>(cells[c]), sizeof(int) ); + out.write( (char*)&val<6>(cells[c]), sizeof(int) ); + out.write( (char*)&val<8>(cells[c]), sizeof(int) ); + out.write( (char*)&val<7>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 8 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 11; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + //float tmp = (float)nodedata[s][d]; + //out.write((char*)&tmp,sizeof(float)); + double tmp = nodedata[s][d]; + out.write((char*)&tmp,sizeof(double)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +/*===============================================================================*/ +string WbWriterVtkXmlBinary::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + int nofCells = (int)cells.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int ); + int bytesCellOffsets = 1 /*offset per oct*/ * nofCells * sizeof(int ); + int bytesCellTypes = 1 /*type of oct */ * nofCells * sizeof(unsigned char); + //int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(float); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&val<1>(cells[c]), sizeof(int) ); + out.write( (char*)&val<2>(cells[c]), sizeof(int) ); + out.write( (char*)&val<4>(cells[c]), sizeof(int) ); + out.write( (char*)&val<3>(cells[c]), sizeof(int) ); + out.write( (char*)&val<5>(cells[c]), sizeof(int) ); + out.write( (char*)&val<6>(cells[c]), sizeof(int) ); + out.write( (char*)&val<8>(cells[c]), sizeof(int) ); + out.write( (char*)&val<7>(cells[c]), sizeof(int) ); + } + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + int itmp; + for(int c=1; c<=nofCells; c++) + { + itmp = 8 * c; + out.write( (char*)&itmp, sizeof(int) ); + } + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 11; + for(int c=0; c<nofCells; c++) + { + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +std::string WbWriterVtkXmlBinary::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 1 /*nodes per cell */ * nofNodes * sizeof(int ); + int bytesCellOffsets = 1 /*offset per cell */ * nofNodes * sizeof(int ); + int bytesCellTypes = 1 /*type of line */ * nofNodes * sizeof(unsigned char); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofNodes; c++) + out.write( (char*)&c, sizeof(int) ); + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + for(int c=1; c<=nofNodes; c++) + out.write( (char*)&c, sizeof(int) ); + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 1; + for(int c=0; c<nofNodes; c++) + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - end"); + + return vtkfilename; +} +std::string WbWriterVtkXmlBinary::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) +{ + string vtkfilename = filename+getFileExtension(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - start"); + + ofstream out(vtkfilename.c_str(),ios::out | ios::binary); + if(!out) + { + out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!! + string path = UbSystem::getPathFromString(vtkfilename); + if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);} + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename); + } + + int nofNodes = (int)nodes.size(); + + int bytesPerByteVal = 4; //==sizeof(int) + int bytesPoints = 3 /*x1/x2/x3 */ * nofNodes * sizeof(float); + int bytesCellConnectivty = 1 /*nodes per cell */ * nofNodes * sizeof(int ); + int bytesCellOffsets = 1 /*offset per cell*/ * nofNodes * sizeof(int ); + int bytesCellTypes = 1 /*type of oct */ * nofNodes * sizeof(unsigned char); + int bytesScalarData = 1 /*scalar */ * nofNodes * sizeof(double); + + int offset = 0; + //VTK FILE + out<<"<?xml version=\"1.0\"?>\n"; + out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n"; + out<<" <UnstructuredGrid>"<<"\n"; + out<<" <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n"; + + //POINTS SECTION + out<<" <Points>\n"; + out<<" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + out<<" </Points>\n"; + offset += (bytesPerByteVal + bytesPoints); + + //CELLS SECTION + out<<" <Cells>\n"; + out<<" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellConnectivty); + out<<" <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; + offset += (bytesPerByteVal + bytesCellOffsets); + out<<" <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n "; + offset += (bytesPerByteVal + bytesCellTypes); + out<<" </Cells>\n"; + + //DATA SECTION + out<<" <PointData>\n"; + for(size_t s=0; s<datanames.size(); ++s) + { + out<< " <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n"; + offset += (bytesPerByteVal + bytesScalarData); + } + out<<" </PointData>\n"; + + out<<" </Piece>\n"; + out<<" </UnstructuredGrid>\n"; + + // AppendedData SECTION + out<<" <AppendedData encoding=\"raw\">\n"; + out<<"_"; + + //POINTS SECTION + out.write((char*)&bytesPoints,bytesPerByteVal); + for(int n=0; n<nofNodes; n++) + { + out.write((char*)&val<1>(nodes[n]),sizeof(float)); + out.write((char*)&val<2>(nodes[n]),sizeof(float)); + out.write((char*)&val<3>(nodes[n]),sizeof(float)); + } + + //CELLS SECTION + //cellConnectivity + out.write( (char*)&bytesCellConnectivty, bytesPerByteVal ); + for(int c=0; c<nofNodes; c++) + out.write( (char*)&c, sizeof(int) ); + + //cellOffsets + out.write( (char*)&bytesCellOffsets, bytesPerByteVal ); + for(int c=1; c<=nofNodes; c++) + out.write( (char*)&c, sizeof(int) ); + + //cellTypes + out.write( (char*)&bytesCellTypes, bytesPerByteVal ); + unsigned char vtkCellType = 1; + for(int c=0; c<nofNodes; c++) + out.write( (char*)&vtkCellType, sizeof(unsigned char) ); + + //DATA SECTION + //scalarData + for(size_t s=0; s<datanames.size(); ++s) + { + out.write((char*)&bytesScalarData,bytesPerByteVal); + for(size_t d=0; d<nodedata[s].size(); ++d) + { + //loake kopie machen, da in nodedata "doubles" sind + //float tmp = (float)nodedata[s][d]; + //out.write((char*)&tmp,sizeof(float)); + double tmp = nodedata[s][d]; + out.write((char*)&tmp, sizeof(double)); + } + } + out<<"\n</AppendedData>\n"; + out<<"</VTKFile>"; + out<<endl; + out.close(); + UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - end"); + + return vtkfilename; + +} diff --git a/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.h b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.h new file mode 100644 index 0000000000000000000000000000000000000000..cd0182c26aedfa6097602f85ff2e3ccb4bb6d499 --- /dev/null +++ b/VirtualFluidsBasics/basics/writer/WbWriterVtkXmlBinary.h @@ -0,0 +1,121 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WbWriterVtkXmlBinary.h +//! \ingroup writer +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef WBWRITERVTKXMLBINARY_H +#define WBWRITERVTKXMLBINARY_H + +#include <string> + +#include <basics/writer/WbWriter.h> + +class WbWriterVtkXmlBinary : public WbWriter +{ +public: + static WbWriterVtkXmlBinary* getInstance() + { + static WbWriterVtkXmlBinary instance; + return &instance; + } +private: + WbWriterVtkXmlBinary() : WbWriter() + { + if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"machine error char type mismatch"); + if(sizeof(int) !=4) throw UbException(UB_EXARGS,"machine error int type mismatch"); + if(sizeof(float) !=4) throw UbException(UB_EXARGS,"machine error float type mismatch"); + } + + WbWriterVtkXmlBinary( const WbWriterVtkXmlBinary& ); //no copy allowed + const WbWriterVtkXmlBinary& operator=( const WbWriterVtkXmlBinary& ); //no copy allowed + + static std::string pvdEndTag; +public: + std::string getFileExtension() { return ".bin.vtu"; } + + //write a metafile + std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups); + std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups); + std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames); + + ////////////////////////////////////////////////////////////////////////// + //nodes + std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes); + std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //lines + // 0 ---- 1 + //nodenumbering must start with 0! + std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines); + std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //triangles + // 2 + // + // 0---1 + //nodenumbering must start with 0! + std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles); + std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata); + + ////////////////////////////////////////////////////////////////////////// + //2D + //cell numbering: + // 3---2 + // | | + // 0---1 + //nodenumbering must start with 0! + + std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells); + std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata); + std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata); + std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, + std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, + std::vector< std::vector< double > >& celldata ); + + ////////////////////////////////////////////////////////////////////////// + //octs + // 7 ---- 6 + // /| /| + // 4 +--- 5 | + // | | | | + // | 3 ---+ 2 + // |/ |/ + // 0 ---- 1 + std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells); + std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata); + std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata); + +private: + +}; + +#endif //WBWRITERVTKXMLBINARY_H diff --git a/VirtualFluidsBasics/geometry3d/CMakePackage.txt b/VirtualFluidsBasics/geometry3d/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..e3e3f9a387b022a62ecc0d63c3ef0210313e906d --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) \ No newline at end of file diff --git a/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.cpp b/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d92075c9e7910f59cfe5c9b0cc070083507c5ce2 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.cpp @@ -0,0 +1,288 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CoordinateTransformation3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <geometry3d/CoordinateTransformation3D.h> +#include <basics/utilities/UbMath.h> + +using namespace std; + +CoordinateTransformation3D::CoordinateTransformation3D() +{ + this->setTransformationValues(0.0,0.0,0.0,1.0,1.0,1.0,0.0,0.0,0.0); +} +/*======================================================*/ +CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma) +{ + this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, alpha, beta, gamma); +} +/*======================================================*/ +CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3) +{ + this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, 0.0, 0.0, 0.0); +} +/*======================================================*/ +CoordinateTransformation3D::CoordinateTransformation3D(CoordinateTransformation3D* transformation) +{ + this->setTransformationValues(transformation->Tx1 , transformation->Tx2 , transformation->Tx3 , transformation->Sx1 , transformation->Sx2 , transformation->Sx3, transformation->alpha, transformation->beta, transformation->gamma); +} +/*======================================================*/ +// void CoordinateTransformation3D::init() +// { +// this->Tx1 = 0.0; this->Tx2 = 0.0; this->Tx3 = 0.0; +// this->Sx1 = 1.0; this->Sx2 = 1.0; this->Sx3 = 1.0; +// this->alpha = 0.0; this->beta = 0.0; this->gamma = 0.0; +// +// this->toX1factorX1 = 1.0; this->toX1factorX2 = 0.0; this->toX1factorX3 = 0.0; +// this->toX2factorX1 = 0.0; this->toX2factorX2 = 1.0; this->toX2factorX3 = 0.0; +// this->toX3factorX1 = 0.0; this->toX3factorX2 = 0.0; this->toX3factorX3 = 1.0; +// this->toX1delta = 0.0; this->toX2delta = 0.0; this->toX3delta = 0.0; +// this->fromX1factorX1 = 1.0; this->fromX1factorX2 = 0.0; this->fromX1factorX3 = 0.0; +// this->fromX2factorX1 = 0.0; this->fromX2factorX2 = 1.0; this->fromX2factorX3 = 0.0; +// this->fromX3factorX1 = 0.0; this->fromX3factorX2 = 0.0; this->fromX3factorX3 = 1.0; +// +// this->active = false; +// this->transformation = false; +// } +/*======================================================*/ + +/**==== Set transformation values ====**/ +/*! +\brief Set transformation values +@param a transformed coordinate system x0 (in global coordinates) +@param b transformed coordinate system y0 (in global coordinates) +@param c transformed coordinate system z0 (in global coordinates) +@param dx1 x coordinate scaling (dx_transformed/dx_global) +@param dx2 y coordinate scaling (dy_transformed/dy_global) +@param dx3 z coordinate scaling (dz_transformed/dz_global) +@param alpha rotation around z angle (positive FROM global TO transformed coordinate system) +@param beta rotation around y angle +@param gamma rotation around x angle +@exception IllegalArgumentException if c1 of the scale values is between -1.0E-8 and 1.0E-8 +*/ + +void CoordinateTransformation3D::setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma) +{ + if(UbMath::zero(dx1) || UbMath::zero(dx2) || UbMath::zero(dx3)) + throw UbException(UB_EXARGS,"error: at least one delta==0.0"); + + this->Tx1 = originX1; this->Tx2 = originX2; this->Tx3 = originX3; + this->Sx1 = dx1; this->Sx2 = dx2; this->Sx3 = dx3; + this->alpha = alpha; this->beta = beta; this->gamma = gamma; + + double ra = UbMath::PI*alpha/180.0; + double cosA = cos(ra); + double sinA = sin(ra); + double rb = UbMath::PI*beta/180.0; + double cosB = cos(rb); + double sinB = sin(rb); + double rg = UbMath::PI*gamma/180.0; + double cosG = cos(rg); + double sinG = sin(rg); + + //Matrix-Werte von T_invers (indizes: 12 = spalte 1 zeile 2) + double divisor = (Sx1*Sx2*Sx3); + + this->toX1factorX1 = +cosB*cosA*Sx2*Sx3/divisor; + this->toX1factorX2 = -cosB*sinA*Sx1*Sx3/divisor; + this->toX1factorX3 = +sinB*Sx1*Sx2/divisor; + this->toX1delta = (-Tx3*Sx1*Sx2*sinB + +Tx2*Sx1*Sx3*sinA*cosB + -Tx1*Sx2*Sx3*cosB*cosA)/divisor; + + this->toX2factorX1 = Sx2*Sx3*(sinG*sinB*cosA+cosG*sinA)/divisor; + this->toX2factorX2 = Sx1*Sx3*(-sinG*sinB*sinA+cosG*cosA)/divisor; + this->toX2factorX3 = -Sx1*Sx2*cosB*sinG/divisor; + this->toX2delta = (-Tx2*Sx1*Sx3*cosG*cosA + +Tx3*Sx1*Sx2*sinG*cosB + +Tx2*Sx1*Sx3*sinG*sinA*sinB + -Tx1*Sx2*Sx3*cosG*sinA + -Tx1*Sx2*Sx3*sinB*sinG*cosA )/divisor; + + + this->toX3factorX1 = Sx2*Sx3*(-cosG*sinB*cosA+sinG*sinA)/divisor; + this->toX3factorX2 = Sx1*Sx3*(sinB*cosG*sinA+sinG*cosA)/divisor; + this->toX3factorX3 = Sx1*Sx2*cosB*cosG/divisor; + this->toX3delta = (-Tx2*Sx1*Sx3*sinG*cosA + -Tx3*Sx1*Sx2*cosG*cosB + -Tx2*Sx1*Sx3*cosG*sinA*sinB + -Tx1*Sx2*Sx3*sinG*sinA + +Tx1*Sx2*Sx3*sinB*cosG*cosA )/divisor; + + //Matrix-Werte von T_invers (indizes: 12 = spalte 1 zeile 2) + this->fromX1factorX1 = cosB*cosA*Sx1; + this->fromX1factorX2 = (sinG*sinB*cosA+cosG*sinA)*Sx1; + this->fromX1factorX3 = (-cosG*sinB*cosA+sinG*sinA)*Sx1; + this->fromX1delta = Tx1; + + this->fromX2factorX1 = -cosB*sinA*Sx2; + this->fromX2factorX2 = -(sinG*sinB*sinA-cosG*cosA)*Sx2; + this->fromX2factorX3 = (cosG*sinB*sinA+sinG*cosA)*Sx2; + this->fromX2delta = Tx2; + + this->fromX3factorX1 = sinB*Sx3; + this->fromX3factorX2 = -sinG*cosB*Sx3; + this->fromX3factorX3 = cosG*cosB*Sx3; + this->fromX3delta = Tx3; + + this->active = true; + + this->transformation = true; +} +/*======================================================*/ +/*! +Set transformation active state (if this IS a transformation) +@param active true to be active, false otherwise +**/ +void CoordinateTransformation3D::setActive(const bool& active) +{ + if(this->active == active) return; + if(this->transformation) this->active = active; +} +/*======================================================*/ +/*! +Transform FROM global coordinates TO transformed coordinates. +@param x1 the global x coordinate +@param x2 the global y coordinate +@param x3 the global z coordinate +**/ +double CoordinateTransformation3D::transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->toX1factorX1*x1 + this->toX1factorX2*x2 + this->toX1factorX3*x3 + this->toX1delta; + else return x1; +} +/*======================================================*/ +double CoordinateTransformation3D::transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->toX2factorX1*x1 + this->toX2factorX2*x2 + this->toX2factorX3*x3 + this->toX2delta; + else return x2; +} +/*======================================================*/ +double CoordinateTransformation3D::transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->toX3factorX1*x1 + this->toX3factorX2*x2 + this->toX3factorX3*x3 + this->toX3delta; + else return x3; +} +/*======================================================*/ +/*! +Transform FROM global coordinates TO transformed coordinates (ignoring rotation). +@param x1 the global x coordinate +**/ +double CoordinateTransformation3D::transformForwardToX1CoordinateIgnoringRotation(const double& x1) const +{ + if(this->active) return (x1-this->Tx1)/this->Sx1; + else return x1; +} +/*======================================================*/ +double CoordinateTransformation3D::transformForwardToX2CoordinateIgnoringRotation(const double& x2) const +{ + if(this->active) return (x2-this->Tx2)/this->Sx2; + else return x2; +} +/*======================================================*/ +double CoordinateTransformation3D::transformForwardToX3CoordinateIgnoringRotation(const double& x3) const +{ + if(this->active) return (x3-this->Tx3)/this->Sx3; + else return x3; +} +/*======================================================*/ +/*! +Transform FROM transformed coordinates TO global coordinates. +@param x1 the transformed x coordinate +@param x2 the transformed y coordinate +@param x3 the transformed z coordinate +**/ +double CoordinateTransformation3D::transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->fromX1factorX1*x1 + this->fromX1factorX2*x2 + this->fromX1factorX3*x3 + this->fromX1delta; + else return x1; +} +/*======================================================*/ +double CoordinateTransformation3D::transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->fromX2factorX1*x1 + this->fromX2factorX2*x2 + this->fromX2factorX3*x3 + this->fromX2delta; + else return x2; +} +/*======================================================*/ +double CoordinateTransformation3D::transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const +{ + if(this->active) return this->fromX3factorX1*x1 + this->fromX3factorX2*x2 + this->fromX3factorX3*x3 + this->fromX3delta; + else return x3; +} +/*======================================================*/ +/*! +Transform FROM transformed coordinates TO global coordinates (ignoring rotation). +@param x1 the transformed x coordinate +**/ +double CoordinateTransformation3D::transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const +{ + if(this->active) return x1*this->Sx1+this->Tx1; + else return x1; +} +/*======================================================*/ +double CoordinateTransformation3D::transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const +{ + if(this->active) return x2*this->Sx2+this->Tx2; + else return x2; +} +/*======================================================*/ +double CoordinateTransformation3D::transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const +{ + if(this->active) return x3*this->Sx3+this->Tx3; + else return x3; +} +/*======================================================*/ +/*! +Returns a string representation of this transformation. +@return a string representation of this transformation +**/ +string CoordinateTransformation3D::toString() const +{ + stringstream ss; + ss<<" CoordinateTransformation3D\n"; +// ss<<"[isTransformation="<<this->transformation; +// ss<<", isActive="<<this->active<<endl; + ss<<" ,a="<<this->Tx1<<", b="<<this->Tx2<<", c="<<this->Tx3<<endl; + ss<<" , dx1="<<this->Sx1<<", dx2="<<this->Sx2<<", dx2="<<this->Sx3<<endl; +// ss<<" , alpha="<<this->alpha<<", beta="<<this->beta<endl; +// ss<<"]"; +// ss<<"[to11="<<this->to11<<", to12="<<this->to12<<", to13="<<this->to13; +// ss<<", to21="<<this->to21<<", to22="<<this->to22<<", to23="<<this->to23; +// ss<<", to31="<<this->to31<<", to32="<<this->to32<<", to33="<<this->to33; +// ss<<", toA="<<this->toA<<", toB="<<this->toB<<", toC="<<this->toC; +// ss<<", from11="<<this->from11<<", from12="<<this->from12<<", from13="<<this->from13; +// ss<<", from21="<<this->from21<<", from22="<<this->from22<<", from23="<<this->from23; +// ss<<", from31="<<this->from31<<", from32="<<this->from32<<", from33="<<this->from33; +// ss<<", fromA="<<this->fromA; ss<<", fromB="<<this->fromB; ss<<", fromC="<<this->fromC; +// ss<<"]}"; + return ss.str(); +} + diff --git a/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.h b/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.h new file mode 100644 index 0000000000000000000000000000000000000000..1f89a5e686efc4e3b0a1c901e0d93d1a25f9a9f4 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/CoordinateTransformation3D.h @@ -0,0 +1,125 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CoordinateTransformation3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef COORDINATETRANSFORMATION3D_H +#define COORDINATETRANSFORMATION3D_H + +#include <cmath> +#include <string> +#include <sstream> + +#include <basics/utilities/UbException.h> + +#include <PointerDefinitions.h> + +/////////////////////////////////////////////////////////////////////////////////////// +//! +//! \brief A class provides 3d coordinate transformation +//! \details +//! description: x1/x2/x3 = old, x1*/x2*/x3* = new +//! x2 +//! ^ x* +//! | / +//! | 2* +//! 4 / +//! | / +//! 3 1* => new coordsys is translated by originX1=originX2=originX3=2 +//! | / new dx1=dx2=dx2=2 -> scaling by 2 in x1-,x2- und x3-direction +//! 2 / FIRST rotation by alpha around "x1" axis +//! | \ THEN rotation by beta around "x2" axis +//! 1 \ THEN rotation by gamma around "x3" axis +//! | x1* +//! |--1--2--3--4--5------------- > x1 +//! +//! Remark: It might be that the rotations around x1 and x3 axis are swapped. +//! +////////////////////////////////////////////////////////////////////////////////////// + +class CoordinateTransformation3D +{ +public: + CoordinateTransformation3D(); + CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma); + CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3); + CoordinateTransformation3D(CoordinateTransformation3D* transformation); + + void setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma); + double getX1CoordinateOffset() const { return this->Tx1; } //Translation + double getX2CoordinateOffset() const { return this->Tx2; } + double getX3CoordinateOffset() const { return this->Tx3; } + double getX1CoordinateScaling() const { return this->Sx1; } //Scaling + double getX2CoordinateScaling() const { return this->Sx2; } + double getX3CoordinateScaling() const { return this->Sx3; } + double getRotationX1Angle() const { return this->alpha; } + double getRotationX2Angle() const { return this->beta; } + double getRotationX3Angle() const { return this->gamma; } //Rotation + + //Achtung die Winkel passen nicht überein -siehe setTransformationValues + void setRotationX1Angle(double alpha) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, alpha, this->beta, this->gamma); } + void setRotationX2Angle(double beta ) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, beta, this->gamma); } + void setRotationX3Angle(double gamma) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, this->beta, gamma); } + + void setActive(const bool& active); + bool isActive() const { return this->active; } + bool isTransformation() const { return this->transformation; } + + double transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformForwardToX1CoordinateIgnoringRotation(const double& x1) const; + double transformForwardToX2CoordinateIgnoringRotation(const double& x2) const; + double transformForwardToX3CoordinateIgnoringRotation(const double& x3) const; + double transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const; + double transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const; + double transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const; + double transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const; + std::string toString() const; + +private: + double Tx1, Tx2, Tx3, Sx1, Sx2, Sx3, alpha, beta, gamma; + + double toX1factorX1, toX1factorX2, toX1factorX3, toX1delta; + double toX2factorX1, toX2factorX2, toX2factorX3, toX2delta; + double toX3factorX1, toX3factorX2, toX3factorX3, toX3delta; + + double fromX1factorX1, fromX1factorX2, fromX1factorX3, fromX1delta; + double fromX2factorX1, fromX2factorX2, fromX2factorX3, fromX2delta; + double fromX3factorX1, fromX3factorX2, fromX3factorX3, fromX3delta; + + bool active; + bool transformation; + +}; + +#endif //COORDINATETRANSFORMATION3D_H diff --git a/VirtualFluidsBasics/geometry3d/GbCuboid3D.cpp b/VirtualFluidsBasics/geometry3d/GbCuboid3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67a7d3d15ea79295fd806b393e002dedfac3c0b9 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbCuboid3D.cpp @@ -0,0 +1,567 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbCuboid3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbCuboid3D.h> +#include <GbSystem3D.h> +#include <GbTriangle3D.h> + +#include <basics/utilities/UbMath.h> + +using namespace std; + +/*=======================================================*/ +// Konstruktor +GbCuboid3D::GbCuboid3D() : GbObject3D() +{ + this->setName("cuboid"); + this->p1 = new GbPoint3D(0.0, 0.0, 0.0); + this->p2 = new GbPoint3D(0.0, 0.0, 0.0); + this->p1->addObserver(this); + this->p2->addObserver(this); +} +/*=======================================================*/ +GbCuboid3D::GbCuboid3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b):GbObject3D() +{ + this->setName("cuboid"); + this->p1 = new GbPoint3D(x1a, x2a, x3a); + this->p1->addObserver(this); + this->p2 = new GbPoint3D(x1b, x2b, x3b); + this->p2->addObserver(this); +} +/*=======================================================*/ +GbCuboid3D::GbCuboid3D(GbPoint3D* p1, GbPoint3D* p2) : GbObject3D() +{ + this->setName("cuboid"); + if(!p1 || !p2) throw UbException(UB_EXARGS,"one point ==NULL"); + this->p1 = p1; + this->p1->addObserver(this); + this->p2 = p2; + this->p2->addObserver(this); +} +/*=======================================================*/ +GbCuboid3D::GbCuboid3D(GbCuboid3D* cuboid) : GbObject3D() +{ + this->setName("cuboid"); + if(!cuboid->getPoint1() || !cuboid->getPoint2()) throw UbException(UB_EXARGS,"cuboid ==NULL"); + this->p1 = cuboid->getPoint1()->clone(); + this->p1->addObserver(this); + this->p2 = cuboid->getPoint2()->clone(); + this->p2->addObserver(this); +} +/*=======================================================*/ +// Destruktor +GbCuboid3D::~GbCuboid3D() +{ + //cout<<"~GbCuboid3D()"<<endl; + if(this->p1) this->p1->removeObserver(this); + if(this->p2) this->p2->removeObserver(this); +} +/*=======================================================*/ +void GbCuboid3D::finalize() +{ + if(this->p1) + { + this->p1->removeObserver(this); + this->p1->finalize(); + delete this->p1; + this->p1=NULL; + } + if(this->p2) + { + this->p2->removeObserver(this); + this->p2->finalize(); + delete this->p2; + this->p2=NULL; + } +} +/*=======================================================*/ +void GbCuboid3D::setPoint1(GbPoint3D* point1) +{ + if(this->p1) this->p1->removeObserver(this); + this->p1 = point1; + this->p1->addObserver(this); + + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbCuboid3D::setPoint2(GbPoint3D* point2) +{ + if(this->p2) this->p2->removeObserver(this); + this->p2 = point2; + this->p2->addObserver(this); + + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbCuboid3D::setPoints(GbPoint3D* point1, GbPoint3D* point2) +{ + if(this->p1) this->p1->removeObserver(this); + if(this->p2) this->p2->removeObserver(this); + + this->p1 = point1; + this->p2 = point2; + + this->p1->addObserver(this); + this->p2->addObserver(this); + + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbCuboid3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) +{ + this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() ); +} +/*=======================================================*/ +double GbCuboid3D::getX1Centroid() +{ + return (0.5*(p1->x1 + p2->x1)); +} +/*=======================================================*/ +double GbCuboid3D::getX1Minimum() +{ + return (this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1); +} +/*=======================================================*/ +double GbCuboid3D::getX1Maximum() +{ + return (this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1); +} +/*=======================================================*/ +double GbCuboid3D::getX2Centroid() +{ + return (0.5*(p1->x2 + p2->x2)); +} +/*=======================================================*/ +double GbCuboid3D::getX2Minimum() +{ + return (this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2); +} +/*=======================================================*/ +double GbCuboid3D::getX2Maximum() +{ + return ( this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2); +} +/*=======================================================*/ +double GbCuboid3D::getX3Centroid() +{ + return (0.5*(p1->x3 + p2->x3)); +} +/*=======================================================*/ +double GbCuboid3D::getX3Minimum() +{ + return (this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3); +} +/*=======================================================*/ +double GbCuboid3D::getX3Maximum() +{ + return (this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3); +} +/*=======================================================*/ +double GbCuboid3D::getLengthX1() +{ + return (this->getX1Maximum() - this->getX1Minimum() ); +} +/*=======================================================*/ +double GbCuboid3D::getLengthX2() +{ + return (this->getX2Maximum() - this->getX2Minimum()); +} +/*=======================================================*/ +double GbCuboid3D::getLengthX3() +{ + return (this->getX3Maximum() - this->getX3Minimum()); +} +/*=======================================================*/ +bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p) +{ + //true, wenn 'in Object' oder 'auf Boundary'! + if (UbMath::less(x1p,this->getX1Minimum())) return false; + else if(UbMath::less(x2p,this->getX2Minimum())) return false; + else if(UbMath::less(x3p,this->getX3Minimum())) return false; + else if(UbMath::greater(x1p,this->getX1Maximum())) return false; + else if(UbMath::greater(x2p,this->getX2Maximum())) return false; + else if(UbMath::greater(x3p,this->getX3Maximum())) return false; + + return true; +} +/*=======================================================*/ +bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary) +{ + pointIsOnBoundary = false; + + //true, wenn 'in Object' oder 'auf Boundary'! + if (UbMath::less(x1p,this->getX1Minimum())) return false; + else if(UbMath::less(x2p,this->getX2Minimum())) return false; + else if(UbMath::less(x3p,this->getX3Minimum())) return false; + else if(UbMath::greater(x1p,this->getX1Maximum())) return false; + else if(UbMath::greater(x2p,this->getX2Maximum())) return false; + else if(UbMath::greater(x3p,this->getX3Maximum())) return false; + + if (UbMath::equal(x1p,this->getX1Minimum())) pointIsOnBoundary = true; + else if(UbMath::equal(x2p,this->getX2Minimum())) pointIsOnBoundary = true; + else if(UbMath::equal(x3p,this->getX3Minimum())) pointIsOnBoundary = true; + else if(UbMath::equal(x1p,this->getX1Maximum())) pointIsOnBoundary = true; + else if(UbMath::equal(x2p,this->getX2Maximum())) pointIsOnBoundary = true; + else if(UbMath::equal(x3p,this->getX3Maximum())) pointIsOnBoundary = true; + + return true; +} +/*=======================================================*/ +bool GbCuboid3D::isCellInsideGbObject3D(const double& x1p1,const double& x2p1,const double& x3p1,const double& x1p2,const double& x2p2,const double& x3p2) +{ + if ( UbMath::less (x1p1, this->getX1Minimum() ) ) return false; + else if( UbMath::less (x2p1, this->getX2Minimum() ) ) return false; + else if( UbMath::less (x3p1, this->getX3Minimum() ) ) return false; + else if( UbMath::greater(x1p2, this->getX1Maximum() ) ) return false; + else if( UbMath::greater(x2p2, this->getX2Maximum() ) ) return false; + else if( UbMath::greater(x3p2, this->getX3Maximum() ) ) return false; + + return true; +} +/*=======================================================*/ +bool GbCuboid3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung +//returns true: +// - cell cuts cuboid3D +// - cell boxes cuboid3D +//returns false: +// - cell completely inside cuboid3D ( = cuboid3D boxes cell) +// - cell und cuboid3D haben kein gemeinsames Volumen +{ + //erstmal die dumm Loesung + if( !this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) + && this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) ) + { + return true; + } + + return false; + + //GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b); + //if(cube) + //{ + // cube->finalize(); + // delete cube; + // return true; + //} + + //return false; +} +/*=======================================================*/ +bool GbCuboid3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +//returns true: +// - cell completely inside cuboid3D ( = cuboid3D boxes cell) +// - cell cuts cuboid3D +// - cell boxes cuboid3D +//returns false: +// - cell und cuboid3D haben kein gemeinsames Volumen +{ + //simpler check, da unser GbCuboid3D ein AABB is: + // anfA midA endA anfB midB endB + // | x<-- dxA -->| |<-dxB->x | + // |<----------------- T --------------->| + //ist |T| <= dxA + dxB -> overlap! + + if( UbMath::lessEqual( std::fabs( this->getX1Centroid() - 0.5*(x1b+x1a) /*Tx1*/ ) + , 0.5*( this->getLengthX1() + std::fabs(x1b-x1a) /*dx1A+dx1B*/) ) + + && UbMath::lessEqual( std::fabs( this->getX2Centroid() - 0.5*(x2b+x2a) /*Tx2*/ ) + , 0.5*( this->getLengthX2() + std::fabs(x2b-x2a) /*dx2A+dx2B*/) ) + + && UbMath::lessEqual( std::fabs( this->getX3Centroid() - 0.5*(x3b+x3a) /*Tx3*/ ) + , 0.5*( this->getLengthX3() + std::fabs(x3b-x3a) /*dx3A+dx3B*/) ) ) + { + return true; + } + + return false; + + // if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) + // || this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) ) return true; + // + //return false; +} +/*=======================================================*/ +vector<GbTriangle3D*> GbCuboid3D::getSurfaceTriangleSet() +{ + vector<GbTriangle3D*> triangles; + GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum()); + GbPoint3D p2(getX1Maximum(),getX2Minimum(),getX3Minimum()); + GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Minimum()); + GbPoint3D p4(getX1Minimum(),getX2Maximum(),getX3Minimum()); + GbPoint3D p5(getX1Minimum(),getX2Minimum(),getX3Maximum()); + GbPoint3D p6(getX1Maximum(),getX2Minimum(),getX3Maximum()); + GbPoint3D p7(getX1Maximum(),getX2Maximum(),getX3Maximum()); + GbPoint3D p8(getX1Minimum(),getX2Maximum(),getX3Maximum()); + + GbPoint3D pUnten(getX1Centroid(),getX2Centroid(),getX3Minimum()); + GbPoint3D pOben(getX1Centroid(),getX2Centroid(),getX3Maximum()); + GbPoint3D pLinks(getX1Minimum(), getX2Centroid(),getX3Centroid()); + GbPoint3D pRechts(getX1Maximum(), getX2Centroid(),getX3Centroid()); + GbPoint3D pVorne(getX1Centroid(),getX2Minimum(),getX3Centroid()); + GbPoint3D pHinten(getX1Centroid(),getX2Maximum(),getX3Centroid()); + + //"unten" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pUnten),new GbPoint3D(p3))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p1),new GbPoint3D(pUnten))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pUnten),new GbPoint3D(p4))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p4),new GbPoint3D(pUnten))); + //"oben" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(p6),new GbPoint3D(pOben))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p6),new GbPoint3D(p7),new GbPoint3D(pOben))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(pOben),new GbPoint3D(p8))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pOben),new GbPoint3D(p7),new GbPoint3D(p8))); + //"links" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(p1),new GbPoint3D(pLinks))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(pLinks),new GbPoint3D(p8))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p8),new GbPoint3D(pLinks),new GbPoint3D(p5))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pLinks),new GbPoint3D(p1),new GbPoint3D(p5))); + //"rechts" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p3),new GbPoint3D(pRechts))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p3),new GbPoint3D(p7))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pRechts),new GbPoint3D(p6))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p7),new GbPoint3D(p6))); + //"hinten" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(p4),new GbPoint3D(pHinten))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pHinten),new GbPoint3D(p7))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p7),new GbPoint3D(pHinten),new GbPoint3D(p8))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pHinten),new GbPoint3D(p4),new GbPoint3D(p8))); + //"vorne" + triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(pVorne))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p2),new GbPoint3D(p6))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(pVorne),new GbPoint3D(p5))); + triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p6),new GbPoint3D(p5))); + return triangles; +} +/*=======================================================*/ +void GbCuboid3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles) +{ + /*0*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Minimum())); + /*1*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Minimum())); + /*2*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Minimum())); + /*3*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Minimum())); + + /*4*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Maximum())); + /*5*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Maximum())); + /*6*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Maximum())); + /*7*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Maximum())); + + //"unten" + triangles.push_back( makeUbTuple( 0, 1, 2) ); + triangles.push_back( makeUbTuple( 0, 2, 3) ); + //"oben" + triangles.push_back( makeUbTuple( 4, 5, 6) ); + triangles.push_back( makeUbTuple( 4, 6, 7) ); + //"links" + triangles.push_back( makeUbTuple( 0, 3, 7) ); + triangles.push_back( makeUbTuple( 0, 7, 4) ); + //"rechts" + triangles.push_back( makeUbTuple( 1, 2, 6) ); + triangles.push_back( makeUbTuple( 1, 6, 5) ); + //"hinten" + triangles.push_back( makeUbTuple( 3, 2, 7) ); + triangles.push_back( makeUbTuple( 2, 7, 6) ); + //"vorne" + triangles.push_back( makeUbTuple( 0, 1, 5) ); + triangles.push_back( makeUbTuple( 0, 5, 4) ); +} +/*=======================================================*/ +string GbCuboid3D::toString() +{ + stringstream ss; + ss<<"GbCuboid3D["; + ss<<"p1="<<this->p1->toString(); + ss<<", p2="<<this->p2->toString(); + ss<<"]"; + return ss.str(); +} +/*=======================================================*/ +GbPoint3D* GbCuboid3D::calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D& point2) +{ + throw UbException(UB_EXARGS,"not correct implemented"); +} +/*=======================================================*/ +GbLine3D* GbCuboid3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2) +{ + return GbSystem3D::createClipLine3D(point1, point2, + p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(), + p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() ); +} +/*==========================================================*/ +void GbCuboid3D::objectChanged(UbObservable* changedObject) +{ + GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject); + if(!point || (this->p1!=point && this->p2!=point)) return; + + this->notifyObserversObjectChanged(); +} +/*==========================================================*/ +void GbCuboid3D::objectWillBeDeleted(UbObservable* objectForDeletion) +{ + if(this->p1) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1); + if(objectForDeletion == observedObj) { this->p1 = NULL; } + } + if(this->p2) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2); + if(objectForDeletion == observedObj) { this->p2 = NULL; } + } + //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo +} +/*=======================================================*/ +void GbCuboid3D::translate(const double& tx1, const double& tx2, const double& tx3) +{ + this->p1->translate(tx1, tx2, tx3); + this->p2->translate(tx1, tx2, tx3); + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbCuboid3D::scale(const double& sx1, const double& sx2, const double& sx3) +{ + double lenX1 = this->getLengthX1(); + double lenX2 = this->getLengthX2(); + double lenX3 = this->getLengthX3(); + + double deltaX1 = lenX1*sx1 - lenX1; + double deltaX2 = lenX2*sx2 - lenX2; + double deltaX3 = lenX3*sx3 - lenX3; + + double p1X1 = this->p1->getX1Coordinate(); + double p1X2 = this->p1->getX2Coordinate(); + double p1X3 = this->p1->getX3Coordinate(); + + double p2X1 = this->p2->getX1Coordinate(); + double p2X2 = this->p2->getX2Coordinate(); + double p2X3 = this->p2->getX3Coordinate(); + + this->p1->setCoordinates(p1X1 - 0.5*deltaX1 + ,p1X2 - 0.5*deltaX2 + ,p1X3 - 0.5*deltaX3); + + this->p2->setCoordinates(p2X1 + 0.5*deltaX1 + ,p2X2 + 0.5*deltaX2 + ,p2X3 + 0.5*deltaX3); +} +/*==========================================================*/ +double GbCuboid3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +{ + if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) ) return 1.0*(x1b-x1a)*(x2b-x2a)*(x3b-x3a); + if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) ) return 0.0; + + GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b); + + if(cube) + { + double eps; + eps = (cube->getLengthX1())*(cube->getLengthX2())*(cube->getLengthX3()); + cube->finalize(); + delete cube; + return eps; + } + return 0.0; +} +/*==========================================================*/ +double GbCuboid3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3) +{ + double minB[3] = { this->getX1Minimum(), this->getX2Minimum(), this->getX3Minimum() }; + double maxB[3] = { this->getX1Maximum(), this->getX2Maximum(), this->getX3Maximum() }; + double origin[3] = { x1, x2, x3 }; //point + double dir[3] = { rx1, rx2, rx3 }; //ray + + bool inside = true; + char quadrant[3]; + int whichPlane; + double maxT[3]; + double candidatePlane[3]; + + /* Find candidate planes; this loop can be avoided if + rays cast all from the eye(assume perpsective view) */ + for(int i=0; i<3; i++) + { + if(origin[i] < minB[i]) + { + quadrant[i] = 1/*LEFT*/; + candidatePlane[i] = minB[i]; + inside = false; + } + else if(origin[i] > maxB[i]) + { + quadrant[i] = 0/*RIGHT*/; + candidatePlane[i] = maxB[i]; + inside = false; + } + else + { + quadrant[i] = 2/*MIDDLE*/; + } + } + /* Ray origin inside bounding box */ + if(inside) + { + //throw UbException(UB_EXARGS,"not done"); + return 0.0; + } + + /* Calculate T distances to candidate planes */ + for(int i=0; i<3; i++) + { + if( quadrant[i]!=2/*MIDDLE*/ && fabs(dir[i])>1.E-10 ) + { + maxT[i] = (candidatePlane[i]-origin[i])/dir[i]; + } + else maxT[i] = -1.0; + } + + /* Get largest of the maxT's for final choice of intersection */ + whichPlane = 0; + for(int i=1; i<3; i++) + if (maxT[whichPlane] < maxT[i]) + whichPlane = i; + + /* Check final candidate actually inside box */ + if(maxT[whichPlane]< -1.E-10) return -1.0; + double dummy; + for(int i= 0; i<3; i++) + { + if( whichPlane!= i) + { + dummy = origin[i] + maxT[whichPlane]*dir[i]; + if(dummy < minB[i] || dummy > maxB[i]) + return -1.0; + } + } + + return maxT[whichPlane] ; /* ray hits box */ +} + diff --git a/VirtualFluidsBasics/geometry3d/GbCuboid3D.h b/VirtualFluidsBasics/geometry3d/GbCuboid3D.h new file mode 100644 index 0000000000000000000000000000000000000000..db7e0245dbd7b6da344bd26d07a93f8e58c3282d --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbCuboid3D.h @@ -0,0 +1,145 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbCuboid3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBCUBOID3D_H +#define GBCUBOID3D_H + +#include <vector> +#include <cmath> + +#include <GbPoint3D.h> +#include <basics/utilities/UbObserver.h> +#include <basics/utilities/UbMath.h> + +class GbLine3D; +class GbObject3DCreator; + +#include <PointerDefinitions.h> +class GbCuboid3D; +typedef SPtr<GbCuboid3D> GbCuboid3DPtr; + +//! \brief This Class provides basic 3D box objects. +class GbCuboid3D : public GbObject3D, public UbObserver +{ +public: + GbCuboid3D(); + GbCuboid3D(const double& minX1,const double& minX2, const double& minX3, const double& maxX1,const double& maxX2, const double& maxX3); + GbCuboid3D(GbPoint3D *p1, GbPoint3D *p2); + GbCuboid3D(GbCuboid3D *cuboid); + ~GbCuboid3D(); + + GbCuboid3D* clone() { return new GbCuboid3D(this); } + void finalize(); + + GbPoint3D* getPoint1() { return this->p1; } + GbPoint3D* getPoint2() { return this->p2; } + + void setPoint1(GbPoint3D* point1); + void setPoint2(GbPoint3D* point2); + void setPoints(GbPoint3D* point1, GbPoint3D* point2); + + double getX1Centroid(); + double getX1Minimum(); + double getX1Maximum(); + double getX2Centroid(); + double getX2Minimum(); + double getX2Maximum(); + double getX3Centroid(); + double getX3Minimum(); + double getX3Maximum(); + void setCenterCoordinates(const double& x1, const double& x2, const double& x3); + + void translate(const double& x1, const double& x2, const double& x3); + void rotate(const double& rx1, const double& rx2, const double& rx3) {} + void scale(const double& sx1, const double& sx2, const double& sx3); + + double getLengthX1(); + double getLengthX2(); + double getLengthX3(); + + bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary); + bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); + bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + + GbPoint3D* calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D &point2); + //GbCuboid3D* createClippedRectangle3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2); + + std::vector<GbTriangle3D*> getSurfaceTriangleSet(); + void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles); + + bool hasRaytracing() { return true; } + /*|r| must be 1! einheitsvector!!*/ + double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3); + + + double getDistance(GbPoint3D* p) + { + return this->getDistance( p->getX1Coordinate(), p->getX2Coordinate(), p->getX3Coordinate() ); + } + double getDistance(const double& x1p, const double& x2p, const double& x3p) + { + throw UbException( UB_EXARGS, "not implemented" ); + + // falls punkt innerhalt ist: minimalen abstand ausrechnen + if( this->isPointInGbObject3D(x1p,x2p,x3p) ) + { + double x1Dist = UbMath::min( std::abs(x1p-this->getX1Minimum()),std::abs(x1p-this->getX1Maximum()) ); + double x2Dist = UbMath::min( std::abs(x2p-this->getX2Minimum()),std::abs(x2p-this->getX2Maximum()) ); + double x3Dist = UbMath::min( std::abs(x3p-this->getX3Minimum()),std::abs(x3p-this->getX3Maximum()) ); + + return UbMath::min( x1Dist, x2Dist, x3Dist ); + } + else + { + + } + } + + std::string toString(); + + //virtuelle Methoden von UbObserver + void objectChanged(UbObservable* changedObject); + void objectWillBeDeleted(UbObservable* objectForDeletion); + + + using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere + +protected: + GbPoint3D* p1; + GbPoint3D* p2; +}; + +#endif diff --git a/VirtualFluidsBasics/geometry3d/GbLine3D.cpp b/VirtualFluidsBasics/geometry3d/GbLine3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4626eaccbf9c5056ddb0136282aedd9e32d7bd5b --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbLine3D.cpp @@ -0,0 +1,246 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbLine3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbLine3D.h> +#include <GbSystem3D.h> +#include <GbCuboid3D.h> +#include <GbTriangle3D.h> + +using namespace std; + +/*=======================================================*/ +GbLine3D::GbLine3D() +{ + p1 = NULL; + p2 = NULL; + length = 0.0; +} +/*=======================================================*/ +GbLine3D::GbLine3D(GbPoint3D* point1, GbPoint3D* point2) +{ + this->p1 = point1; + this->p2 = point2; + this->p1->addObserver(this); + this->p2->addObserver(this); + this->calculateValues(); +} +/*=======================================================*/ +GbLine3D::GbLine3D(GbLine3D* line) +{ + this->p1 = line->p1->clone(); + this->p2 = line->p2->clone(); + this->p1->addObserver(this); + this->p2->addObserver(this); + this->calculateValues(); +} +/*=======================================================*/ +GbLine3D::~GbLine3D() +{ + if(this->p1) this->p1->removeObserver(this); + if(this->p2) this->p2->removeObserver(this); +} +/*=======================================================*/ +void GbLine3D::finalize() +{ + if(this->p1) + { + this->p1->removeObserver(this); + this->p1->finalize(); + delete this->p1; + this->p1 = NULL; + } + if(this->p2) + { + this->p2->removeObserver(this); + this->p2->finalize(); + delete this->p2; + this->p2 = NULL; + } +} +/*=======================================================*/ +vector<GbTriangle3D*> GbLine3D::getSurfaceTriangleSet() +{ + vector<GbTriangle3D*> triangles; + GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum()); + GbPoint3D p2(getX1Centroid(),getX2Centroid(),getX3Centroid()); + GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Maximum()); + + triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(p3))); + + return triangles; +} +/*=======================================================*/ +void GbLine3D::setPoint1(GbPoint3D* point1) +{ + if(this->p1) this->p1->removeObserver(this); + this->p1 = point1; + this->p1->addObserver(this); + + if(this->p1 && this->p2) this->calculateValues(); +} +/*=======================================================*/ +void GbLine3D::setPoint2(GbPoint3D* point2) +{ + if(this->p2) this->p2->removeObserver(this); + this->p2 = point2; + this->p2->addObserver(this); + + if(this->p1 && this->p2) this->calculateValues(); +} +/*=======================================================*/ +void GbLine3D::setPoints(GbPoint3D* point1, GbPoint3D* point2) +{ + if(this->p1) this->p1->removeObserver(this); + if(this->p2) this->p2->removeObserver(this); + + this->p1 = point1; + this->p2 = point2; + + this->p1->addObserver(this); + this->p2->addObserver(this); + + this->calculateValues(); +} +/*=======================================================*/ +string GbLine3D::toString() +{ + stringstream ss; + ss<<"GbLine3D[p1="; + ss<<this->p1->toString()<<",p2="<<this->p2->toString()<<",l="<<this->getLength()<<"]"; + return(ss.str()); +} +/*=======================================================*/ +GbPoint3D* GbLine3D::calculateIntersectionPoint3D(GbLine3D* line) +{ + throw UbException(UB_EXARGS," not implemented"); + //return(GbSystem::calculateIntersectionPoint3D(*this->p1, *this->p2, *line->p1, *line->p2)); +} +/*======================================================================*/ +GbLine3D* GbLine3D::createClippedLine3D(GbCuboid3D* cuboid) +{ + return GbSystem3D::createClipLine3D(*this->p1, *this->p2, cuboid->getPoint1()->x1, cuboid->getPoint1()->x2, cuboid->getPoint1()->x3, cuboid->getPoint2()->x1, cuboid->getPoint2()->x2, cuboid->getPoint2()->x3); +} +/*======================================================================*/ +GbLine3D* GbLine3D::createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE) +{ + return GbSystem3D::createClipLine3D(*this->p1, *this->p2, pA->x1, pA->x2, pA->x3, pE->x1, pE->x2, pE->x3); +} +/*======================================================================*/ +double GbLine3D::getDistance(const GbPoint3D& point) +{ + return this->getDistance(point.x1,point.x2,point.x3); +} +/*======================================================================*/ +double GbLine3D::getDistance(const double& x1,const double& x2,const double& x3) +{ + double dx1 = this->p2->x1 - this->p1->x1; + double dx2 = this->p2->x2 - this->p1->x2; + double dx3 = this->p2->x3 - this->p1->x3; + + //double vec[3]; + double a0 = x1 - p1->x1; + double a1 = x2 - p1->x2; + double a2 = x3 - p1->x3; + + double kreuzProd0 = a1 * dx3 - a2 * dx2; + double kreuzProd1 = a2 * dx1 - a0 * dx3; + double kreuzProd2 = a0 * dx2 - a1 * dx1; + + return (std::sqrt(kreuzProd0*kreuzProd0+kreuzProd1*kreuzProd1+kreuzProd2*kreuzProd2))/length; +} +/*=======================================================*/ +void GbLine3D::calculateValues() +{ + double dx1 = this->p2->x1 - this->p1->x1; + double dx2 = this->p2->x2 - this->p1->x2; + double dx3 = this->p2->x3 - this->p1->x3; + this->length = std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3); +} +/*==========================================================*/ +void GbLine3D::objectChanged(UbObservable* changedObject) +{ + GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject); + if(!point || (this->p1!=point && this->p2!=point)) return; + + this->calculateValues(); +} +/*==========================================================*/ +void GbLine3D::objectWillBeDeleted(UbObservable* objectForDeletion) +{ + if(this->p1) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1); + if(objectForDeletion == observedObj) { this->p1 = NULL; length = 0.0; } + } + if(this->p2) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2); + if(objectForDeletion == observedObj) { this->p2 = NULL; length = 0.0; } + } + //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo +} +/*==========================================================*/ +void GbLine3D::scale(const double& sx1, const double& sx2, const double& sx3) +{ + double p1X1 = this->p1->getX1Coordinate(); + double p1X2 = this->p1->getX2Coordinate(); + double p1X3 = this->p1->getX3Coordinate(); + + double p2X1 = this->p2->getX1Coordinate(); + double p2X2 = this->p2->getX2Coordinate(); + double p2X3 = this->p2->getX3Coordinate(); + + double lenX1 = fabs( p1X1 - p2X1 ); + double lenX2 = fabs( p1X2 - p2X2 ); + double lenX3 = fabs( p1X3 - p2X3 ); + + double deltaX1 = lenX1*sx1 - lenX1; + double deltaX2 = lenX2*sx2 - lenX2; + double deltaX3 = lenX3*sx3 - lenX3; + + if(p1X1<p2X1) { p1X1 -= 0.5*deltaX1; p2X1 += 0.5*deltaX1; } + else { p1X1 += 0.5*deltaX1; p2X1 -= 0.5*deltaX1; } + if(p1X2<p2X2) { p1X2 -= 0.5*deltaX2; p2X2 += 0.5*deltaX2; } + else { p1X2 += 0.5*deltaX2; p2X2 -= 0.5*deltaX2; } + if(p1X3<p2X3) { p1X3 -= 0.5*deltaX3; p2X3 += 0.5*deltaX3; } + else { p1X3 += 0.5*deltaX3; p2X3 -= 0.5*deltaX3; } + + this->p1->setCoordinates(p1X1,p1X2,p1X3); + this->p2->setCoordinates(p2X1,p2X2,p2X3); +} +/*=======================================================*/ +void GbLine3D::translate(const double& tx1, const double& tx2, const double& tx3) +{ + this->p1->translate(tx1, tx2, tx3); + this->p2->translate(tx1, tx2, tx3); + //this->notifyObserversObjectChanged(); +} diff --git a/VirtualFluidsBasics/geometry3d/GbLine3D.h b/VirtualFluidsBasics/geometry3d/GbLine3D.h new file mode 100644 index 0000000000000000000000000000000000000000..69d6de96d3516d89a0faabcd47ef62d4a30a48e9 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbLine3D.h @@ -0,0 +1,135 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbLine3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBLINE3D_H +#define GBLINE3D_H + +#include <sstream> +#include <cmath> + +#include <basics/utilities/UbObserver.h> + +#include <GbObject3D.h> +#include <GbPoint3D.h> + +class GbCuboid3D; + +#include <PointerDefinitions.h> + +////////////////////////////////////////////////////////////////////////// +//! +//! \class GbLine3D +//! +//! \brief This Class provides basic 3D line objects. +//! \details The describing points are observed by 3D line objects. +//! +////////////////////////////////////////////////////////////////////////// + +class GbLine3D : public GbObject3D , public UbObserver +{ +public: + GbLine3D(); + GbLine3D(GbPoint3D* point1, GbPoint3D* point2); + GbLine3D(GbLine3D* line); + ~GbLine3D(); + + GbLine3D* clone() { return new GbLine3D(this); } + void finalize(); + + void setPoint1(GbPoint3D* point1); + void setPoint2(GbPoint3D* point2); + void setPoints(GbPoint3D* point1, GbPoint3D* point2); + + void deletePoint1() { if(this->p1) {this->p1->removeObserver(this); delete this->p1; this->p1=NULL;} } + void deletePoint2() { if(this->p2) {this->p2->removeObserver(this); delete this->p2; this->p2=NULL;} } + void deletePoints() { this->deletePoint1(); this->deletePoint2(); } + + GbPoint3D* getPoint1() { return this->p1; } + GbPoint3D* getPoint2() { return this->p2; } + + double getLength() { return(this->length); } + + double getX1Centroid() { return((this->p1->x1+this->p2->x1)*0.5);} + double getX2Centroid() { return((this->p1->x2+this->p2->x2)*0.5); }; + double getX3Centroid() { return((this->p1->x3+this->p2->x3)*0.5); } + + double getX1Minimum() { return(this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1); } + double getX2Minimum() { return(this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2); } + double getX3Minimum() { return(this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3); } + + double getX1Maximum() { return(this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1); } + double getX2Maximum() { return(this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2); } + double getX3Maximum() { return(this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3); } + + void scale(const double& sx1, const double& sx2, const double& sx3); + void translate(const double& tx1, const double& tx2, const double& tx3); + + GbPoint3D* calculateIntersectionPoint3D(GbLine3D* line); + GbLine3D* createClippedLine3D(GbCuboid3D* cuboid); + GbLine3D* createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE); + + double getDistance(const GbPoint3D& point); + double getDistance(const double& x1,const double& x2,const double& x3); + + std::vector<GbTriangle3D*> getSurfaceTriangleSet(); + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3) + { + throw UbException(UB_EXARGS,"not implemented"); + } + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary) + { + throw UbException(UB_EXARGS,"not implemented"); + } + bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x32) { return false; } + + GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2) + { + throw UbException(UB_EXARGS,"not implemented"); + } + + //virtuelle Methoden von UbObserver + void objectChanged(UbObservable* changedObject); + void objectWillBeDeleted(UbObservable* objectForDeletion); + + std::string toString(); + + using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere +protected: + GbPoint3D* p1; + GbPoint3D* p2; + double length; + +private: + void calculateValues(); +}; + +#endif diff --git a/VirtualFluidsBasics/geometry3d/GbObject3D.cpp b/VirtualFluidsBasics/geometry3d/GbObject3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77a17ac1505ebe72ae9a7d88221fd47c4a9731ef --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbObject3D.cpp @@ -0,0 +1,115 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbObject3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbObject3D.h> +#include <GbPoint3D.h> +#include <basics/utilities/UbMath.h> + +using namespace std; + +/*======================================================================*/ +bool GbObject3D::isPointInGbObject3D(GbPoint3D* p) +{ + return this->isPointInGbObject3D(p->getX1Centroid(),p->getX2Coordinate(),p->getX3Coordinate()); +} +/*======================================================================*/ +bool GbObject3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +{ + + if( this->isPointInGbObject3D(x1a, x2a, x3a) + && this->isPointInGbObject3D(x1b, x2a, x3a) + && this->isPointInGbObject3D(x1b, x2b, x3a) + && this->isPointInGbObject3D(x1a, x2b, x3a) + && this->isPointInGbObject3D(x1a, x2a, x3b) + && this->isPointInGbObject3D(x1b, x2a, x3b) + && this->isPointInGbObject3D(x1b, x2b, x3b) + && this->isPointInGbObject3D(x1a, x2b, x3b)) + { + return true; + } + + return false; +} +/*======================================================================*/ +bool GbObject3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +{ + if( this->isPointInGbObject3D(x1a, x2a, x3a) + || this->isPointInGbObject3D(x1b, x2a, x3a) + || this->isPointInGbObject3D(x1b, x2b, x3a) + || this->isPointInGbObject3D(x1a, x2b, x3a) + || this->isPointInGbObject3D(x1a, x2a, x3b) + || this->isPointInGbObject3D(x1b, x2a, x3b) + || this->isPointInGbObject3D(x1b, x2b, x3b) + || this->isPointInGbObject3D(x1a, x2b, x3b) ) + { + if( !this->isPointInGbObject3D(x1a, x2a, x3a) + || !this->isPointInGbObject3D(x1b, x2a, x3a) + || !this->isPointInGbObject3D(x1b, x2b, x3a) + || !this->isPointInGbObject3D(x1a, x2b, x3a) + || !this->isPointInGbObject3D(x1a, x2a, x3b) + || !this->isPointInGbObject3D(x1b, x2a, x3b) + || !this->isPointInGbObject3D(x1b, x2b, x3b) + || !this->isPointInGbObject3D(x1a, x2b, x3b)) return true; + } + return false; +} +/*======================================================================*/ +bool GbObject3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) +{ + if( this->isPointInGbObject3D(x1a, x2a, x3a) + || this->isPointInGbObject3D(x1b, x2a, x3a) + || this->isPointInGbObject3D(x1b, x2b, x3a) + || this->isPointInGbObject3D(x1a, x2b, x3a) + || this->isPointInGbObject3D(x1a, x2a, x3b) + || this->isPointInGbObject3D(x1b, x2a, x3b) + || this->isPointInGbObject3D(x1b, x2b, x3b) + || this->isPointInGbObject3D(x1a, x2b, x3b)) + { + return true; + } + + return false; +} +/*=======================================================*/ +bool GbObject3D::isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3) +{ + if( UbMath::greaterEqual(this->getX1Minimum(),minX1) + && UbMath::greaterEqual(this->getX2Minimum(),minX2) + && UbMath::greaterEqual(this->getX3Minimum(),minX3) + && UbMath::lessEqual(this->getX1Maximum(),maxX1) + && UbMath::lessEqual(this->getX2Maximum(),maxX2) + && UbMath::lessEqual(this->getX2Maximum(),maxX3) ) return true; + + return false; +} + + diff --git a/VirtualFluidsBasics/geometry3d/GbObject3D.h b/VirtualFluidsBasics/geometry3d/GbObject3D.h new file mode 100644 index 0000000000000000000000000000000000000000..dcb27c94ea1390c4458e05fe397a9377846ae5ec --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbObject3D.h @@ -0,0 +1,152 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbObject3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBOBJECT3D_H +#define GBOBJECT3D_H + +#include <string> +#include <vector> + + +#include <basics/utilities/UbSystem.h> +#include <basics/utilities/UbException.h> +#include <basics/utilities/UbObservable.h> +#include <basics/utilities/UbTuple.h> +#include <basics/objects/ObObject.h> + +class GbPoint3D; +class GbLine3D; +class GbTriangle3D; +class GbObject3DCreator; + +#include <PointerDefinitions.h> + +////////////////////////////////////////////////////////////////////////// +//! +//! \class GbObject3D +//! +//! \brief This Interface provides basic 3D geometry objects methods. +//! +////////////////////////////////////////////////////////////////////////// + +class GbObject3D : public ObObject +{ +public: + virtual ~GbObject3D(){} + + //abstract Methods + virtual void finalize() =0 ; //detroys also all dynamic objects (e.g. GbPoints in GbLine) + /** + * Returns the centroid x1 coordinate of this 3D object. + * @return the centroid x1 coordinate of this 3D object + */ + virtual double getX1Centroid()=0; + /** + * Returns the minimum x1 coordinate of this 3D object. + * @return the minimum x1 coordinate of this 3D object + */ + virtual double getX1Minimum()=0; + /** + * Returns the maximum x1 coordinate of this 3D object. + * @return the maximum x1 coordinate of this 3D object + */ + virtual double getX1Maximum()=0; + /** + * Returns the centroid x2 coordinate of this 3D object. + * @return the centroid x2 coordinate of this 3D object + */ + virtual double getX2Centroid()=0; + /** + * Returns the minimum x2 coordinate of this 3D object. + * @return the minimum x2 coordinate of this 3D object + */ + virtual double getX2Minimum()=0; + /** + * Returns the maximum x2 coordinate of this 3D object. + * @return the maximum x2 coordinate of this 3D object + */ + virtual double getX2Maximum()=0; + + virtual double getX3Centroid()=0; + /** + * Returns the minimum x2 coordinate of this 3D object. + * @return the minimum x2 coordinate of this 3D object + */ + virtual double getX3Minimum()=0; + /** + * Returns the maximum x2 coordinate of this 3D object. + * @return the maximum x2 coordinate of this 3D object + */ + virtual double getX3Maximum()=0; + + /*=======================================================*/ + double getLengthX1() { return (getX1Maximum()-getX1Minimum()); } + double getLengthX2() { return (getX2Maximum()-getX2Minimum()); } + double getLengthX3() { return (getX3Maximum()-getX3Minimum()); } + + virtual void setCenterX1Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual void setCenterX2Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual void setCenterX3Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual void setCenterCoordinates(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS, "not implemented for " + (std::string)typeid(*this).name()); } + virtual void setCenterCoordinates(const UbTupleDouble3& position) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + //Rotates the Point in relation to the origen. + //Parameters must be radian measure. + virtual void rotate(const double& rx1, const double& rx2, const double& rx3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual void translate(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + virtual void scale(const double& sx1, const double& sx2, const double& sx3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); } + + virtual bool isPointInGbObject3D(GbPoint3D* p); + virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)=0; + virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)=0; + + virtual bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + virtual bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + virtual bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b); + virtual double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b){ return -1.0;}; + + virtual bool isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3); + + virtual GbLine3D* createClippedLine3D (GbPoint3D &point1, GbPoint3D &point2)=0; + virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet()=0; + + virtual void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles) { throw UbException("GbObject3D::addSurfaceTriangleSet - not implemented for "+(std::string)typeid(*this).name()); } + + virtual bool hasRaytracing() { return false; } + virtual bool raytracingSupportsPointsInside() { return false; } + //|r| must be 1! einheitsvector!! + //return negativ value oder zero if no intersection + virtual double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3) { throw UbException("GbObject3D::getIntersectionRaytraceFactor - not implemented"); } +}; +/*=========================================================================*/ + +#endif diff --git a/VirtualFluidsBasics/geometry3d/GbPoint3D.cpp b/VirtualFluidsBasics/geometry3d/GbPoint3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0a179e695bf7b70c3dbc650ca9466ac3f3ee76f --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbPoint3D.cpp @@ -0,0 +1,150 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbPoint3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbPoint3D.h> +using namespace std; + +/*=======================================================*/ +GbPoint3D::GbPoint3D() +{ + this->x1=0.0; + this->x2=0.0; + this->x3=0.0; +} +/*=======================================================*/ +GbPoint3D::GbPoint3D(const double& x1, const double& x2, const double& x3) +{ + this->x1=x1; + this->x2=x2; + this->x3=x3; +} +/*=======================================================*/ +GbPoint3D::GbPoint3D(GbPoint3D* point) +{ + this->x1 = point->x1; + this->x2 = point->x2; + this->x3 = point->x3; +} +/*=======================================================*/ +double GbPoint3D::getDistance(GbPoint3D* p) +{ + double dx1 = this->x1 - p->x1; + double dx2 = this->x2 - p->x2; + double dx3 = this->x3 - p->x3; + return std::sqrt(dx1*dx1 + dx2*dx2 + dx3*dx3); +} +/*=======================================================*/ +bool GbPoint3D::equals(const GbPoint3D* point) const +{ + if(fabs(this->x1-point->x1)>1.E-10) return false; + if(fabs(this->x2-point->x2)>1.E-10) return false; + if(fabs(this->x3-point->x3)>1.E-10) return false; + + return true; +} +/*=======================================================*/ +void GbPoint3D::transform(const double matrix[4][4]) +{ + double tempX1 = x1; + double tempX2 = x2; + double tempX3 = x3; + x1 = matrix[0][0] * tempX1 + matrix[0][1] * tempX2 + matrix[0][2] * tempX3 + matrix[0][3] * 1.; + x2 = matrix[1][0] * tempX1 + matrix[1][1] * tempX2 + matrix[1][2] * tempX3 + matrix[1][3] * 1.; + x3 = matrix[2][0] * tempX1 + matrix[2][1] * tempX2 + matrix[2][2] * tempX3 + matrix[2][3] * 1.; +} +/*=======================================================*/ +bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3) +{ + return (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 ); +} +/*=======================================================*/ +bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary) +{ + pointIsOnBoundary = (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 ); + return pointIsOnBoundary; +} +/*=======================================================*/ +vector<GbTriangle3D*> GbPoint3D::getSurfaceTriangleSet() +{ + cout<<"GbPoint3D::getSurfaceTriangleSet() - test ... if no exception occurs, everything is fine\n"; + vector<GbTriangle3D*> triangles; + return triangles; //<-empty vector! is okay! + + //old: + //to avoid unnecessary exceptions a point will generate a triangle with + //c3 point with same coordinates + //vector<GbTriangle3D*> triangles; + //GbPoint3D p1(getX1Coordinate(),getX2Coordinate(),getX3Coordinate()); + //triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p1),new GbPoint3D(p1))); +} +/*=======================================================*/ +GbLine3D* GbPoint3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2) +{ + throw UbException(UB_EXARGS,"not implemented"); +} +/*=======================================================*/ +string GbPoint3D::toString() +{ + stringstream ss; + ss<<"GbPoint3D["<<this->x1<<","<<this->x2<<","<<this->x3<<"]"; + return((ss.str()).c_str()); +} +/*=======================================================*/ +void GbPoint3D::translate(const double& dx1, const double& dx2, const double& dx3) +{ + this->x1 += dx1; + this->x2 += dx2; + this->x3 += dx3; + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbPoint3D::rotate(const double& rx1, const double& rx2, const double& rx3) +{ + double newX1 = cos(rx3)*cos(rx2)*x1-x2*sin(rx3)*cos(rx1)+x2*cos(rx3)*sin(rx2)*sin(rx1)+x3*sin(rx3)*sin(rx1)+x3*cos(rx3)*sin(rx2)*cos(rx1); + double newX2 = sin(rx3)*cos(rx2)*x1+x2*cos(rx3)*cos(rx1)+x2*sin(rx3)*sin(rx2)*sin(rx1)-x3*cos(rx3)*sin(rx1)+x3*sin(rx3)*sin(rx2)*cos(rx1); + double newX3 = -sin(rx2)*x1+cos(rx2)*sin(rx1)*x2+cos(rx2)*cos(rx1)*x3; + + this->x1 = newX1; + this->x2 = newX2; + this->x3 = newX3; + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ +void GbPoint3D::scale(const double& sx1, const double& sx2, const double& sx3) +{ + this->x1 *= sx1; + this->x2 *= sx2; + this->x3 *= sx3; + this->notifyObserversObjectChanged(); +} +/*=======================================================*/ + diff --git a/VirtualFluidsBasics/geometry3d/GbPoint3D.h b/VirtualFluidsBasics/geometry3d/GbPoint3D.h new file mode 100644 index 0000000000000000000000000000000000000000..956f10461a8715ee4b80597ecf2a4e702b320fb2 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbPoint3D.h @@ -0,0 +1,109 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbPoint3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBPOINT3D_H +#define GBPOINT3D_H + +#include <string> +#include <sstream> +#include <cmath> + +#include <GbObject3D.h> + +#include <PointerDefinitions.h> + +class GbTriangle3D; + +//! \brief This Class provides basic 3D point objects. +class GbPoint3D : public GbObject3D +{ +public: + GbPoint3D(); + GbPoint3D(const double& x1, const double& x2, const double& x3); + GbPoint3D(GbPoint3D *point); + ~GbPoint3D() {} + + GbPoint3D* clone() {return new GbPoint3D(this);} + void finalize() {} + + void setCoordinates(const double& x1, const double& x2, const double& x3) + { + this->x1=x1; + this->x2=x2; + this->x3=x3; + this->notifyObserversObjectChanged(); + } + void setX1(const double& x1) { this->x1=x1; this->notifyObserversObjectChanged(); } + void setX2(const double& x2) { this->x2=x2; this->notifyObserversObjectChanged(); } + void setX3(const double& x3) { this->x3=x3; this->notifyObserversObjectChanged(); } + + double getX1Coordinate() const { return this->x1; } + double getX2Coordinate() const { return this->x2; } + double getX3Coordinate() const { return this->x3; } + + void transform(const double matrix[4][4]); + + double getX1Centroid() { return this->x1; } + double getX1Minimum() { return this->x1; } + double getX1Maximum() { return this->x1; } + double getX2Centroid() { return this->x2; } + double getX2Minimum() { return this->x2; } + double getX2Maximum() { return this->x2; } + double getX3Centroid() { return this->x3; } + double getX3Minimum() { return this->x3; } + double getX3Maximum() { return this->x3; } + + void translate(const double& x1, const double& x2, const double& x3); + void rotate(const double& rx1, const double& rx2, const double& rx3); + void scale(const double& sx1, const double& sx2, const double& sx3); + + double getDistance(GbPoint3D *p); + bool equals(const GbPoint3D* point) const; + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary); + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3); + bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; } + + std::vector<GbTriangle3D*> getSurfaceTriangleSet(); + GbLine3D* createClippedLine3D(GbPoint3D &point1, GbPoint3D &point2); + virtual std::string toString(); + + using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren + //, welche sonst hier "ueberdeckt" waere,da es dieselbe methode mit anderen args gibt! + + //member + double x1; + double x2; + double x3; +}; + + +#endif diff --git a/VirtualFluidsBasics/geometry3d/GbPolygon3D.cpp b/VirtualFluidsBasics/geometry3d/GbPolygon3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ba04de82d36371c7939a1a6582d291bd39a03f0 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbPolygon3D.cpp @@ -0,0 +1,356 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbPolygon3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbPolygon3D.h> + +using namespace std; + +int GbPolygon3D::counter = 0; + +GbPolygon3D::GbPolygon3D() +{ + init(); + counter++; + this->ps = new GbSystem3D::PointSet3(0); +} +void GbPolygon3D::init() +{ + x1s = 0.0; + x2s = 0.0; + x1min = 0.0; + x1max = 0.0; + x2min = 0.0; + x2max = 0.0; + // points = NULL; + consistent = false; + ps = NULL; +} + +/*! +* Creates an empty 3D polygon with the specified capacity. +* @param capacity the initial capacity +*/ +GbPolygon3D::GbPolygon3D(int capacity) +{ + init(); + counter++; + this->ps = new GbSystem3D::PointSet3(capacity); + // this.po = new PointObserver(this); +} +/** +* Creates a 3D polygon with the specified points. +* @param points the initial points of the polygon +*/ +GbPolygon3D::GbPolygon3D(vector<GbPoint3D>& points) +{ + init(); + counter++; + this->ps = new GbSystem3D::PointSet3((int)points.size()); + this->addPoints(points); +} +/** +* Creates a 3D polygon as clone of the specified 3D polygon. +* @param polygon the 3D polygon to be cloned +*/ +GbPolygon3D::GbPolygon3D(GbPolygon3D* polygon) +{ + this->init(); + counter++; + this->ps = new GbSystem3D::PointSet3((int)polygon->size()); + vector<GbPoint3D> temp = polygon->getPoints(); + this->addPoints( temp ); +} + +GbPolygon3D::~GbPolygon3D() +{ + counter--; + //if(points) + //for(unsigned u=0; u<points->size(); u++) + //{ + // delete (*points)[u]; + //} + // delete this->points; + delete this->ps; +} + +/*======================================================================*/ +/** +* Returns the number of points. +* @return the number of points +*/ +int GbPolygon3D::size() +{ + return(this->ps->size()); +} +/** +* Returns the number of times this 3D polygon contains the specified point. +* @param point the point +* @return the number of times this 3D polygon contains the specified point +*/ +int GbPolygon3D::contains(GbPoint3D* point) +{ + return(this->ps->contains(point)); +} +/** +* Returns the number of times this 3D polygon contains a point equal to the specified point. +* @param point the point +* @return the number of times this 3D polygon contains a point equal to the specified point +*/ +int GbPolygon3D::containsEqual(GbPoint3D* point) +{ + return(this->ps->containsEqual(point)); +} +/** +* Returns true, if this 3D polygon contains the specified line. +* @param point1 the first point +* @param point2 the second point +* @return true, if this 3D polygon contains the specified line +*/ +bool GbPolygon3D::containsLine(GbPoint3D* point1, GbPoint3D* point2) +{ + return(this->ps->containsLine(point1, point2)); +} +/** +* Returns true, if this 3D polygon contains the specified line. +* @param line the line +* @return true, if this 3D polygon contains the specified line +*/ +bool GbPolygon3D::containsLine(GbLine3D* line) +{ + return(this->ps->containsLine(line->getPoint1(), line->getPoint2())); +} +/** +* Returns the first point. +* @return the first point +*/ +GbPoint3D* GbPolygon3D::getFirstPoint() +{ + return(this->ps->getFirstPoint()); +} +/** +* Returns the last point. +* @return the last point +*/ +GbPoint3D* GbPolygon3D::getLastPoint() +{ + return(this->ps->getLastPoint()); +} +/** +* Returns the specified point. +* @param index the index +* @return the specified point +* @exception ArrayIndexOutOfBoundsException if the specified index is not valid +*/ +GbPoint3D* GbPolygon3D::getPoint(const int& index) +{ + if(index < 0 || index > this->ps->size()) throw UbException(UB_EXARGS,"ArrayIndexOutOfBoundsException-GbPolygon3D.getPoint()"); + return(this->ps->getPoint(index)); +} +/** +* Returns the points. +* @return the points +*/ +vector<GbPoint3D> GbPolygon3D::getPoints() +{ + if(!this->consistent) this->calculateValues(); + return(this->points); +} +/** +* Returns the points within the specified rectangle. +* @param p1 the 1st point of the rectangle +* @param p2 the 2nd point of the rectangle +* @return the points within the specified rectangle +*/ +vector<GbPoint3D> GbPolygon3D::getPoints(GbPoint3D* p1, GbPoint3D* p2) +{ + return(this->getPoints(p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3)); +} +/** +* Returns the points within the specified rectangle. +* @param p1x1 the 1st x1 coordinate of the rectangle +* @param p1x2 the 1st x2 coordinate of the rectangle +* @param p1x3 the 1st x3 coordinate of the rectangle +* @param p2x1 the 2nd x1 coordinate of the rectangle +* @param p2x2 the 2nd x2 coordinate of the rectangle +* @param p2x3 the 2nd x3 coordinate of the rectangle +* @return the points within the specified rectangle +*/ +vector<GbPoint3D> GbPolygon3D::getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3) +{ + double x1min, x1max, x2min, x2max, x3min, x3max; + + if(UbMath::less(p1x1, p2x1)) { x1min = p1x1; x1max = p2x1; } + else { x1min = p2x1; x1max = p1x1; } + if(UbMath::less(p1x2, p2x2)) { x2min = p1x2; x2max = p2x2; } + else { x2min = p2x2; x2max = p1x2; } + if(UbMath::less(p1x3, p2x3)) { x3min = p1x3; x3max = p2x3; } + else { x3min = p2x3; x3max = p1x3; } + + GbSystem3D::PointSet3 *pts = new GbSystem3D::PointSet3(1); + + if(!this->consistent) this->calculateValues(); + for(int i=this->size()-1; i>=0; i--) + { + if(UbMath::lessEqual(x1min, (this->points)[i].x1) && UbMath::greaterEqual(x1max, (this->points)[i].x1) && + UbMath::lessEqual(x2min, (this->points)[i].x2) && UbMath::greaterEqual(x2max, (this->points)[i].x2) && + UbMath::lessEqual(x3min, (this->points)[i].x3) && UbMath::greaterEqual(x3max, (this->points)[i].x3)) pts->add((this->points)[i]); + } + return(pts->getPoints()); +} +/** +* Returns the area of this polygon. +* The area is positive for positive ordered points, otherwise negative. +* @return the area of this polygon +*/ +//double getArea() +//{ +// if(!this.consistent) this.calculateValues(); +// return(this.area); +//} +double GbPolygon3D::getX1Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1s); +} +double GbPolygon3D::getX1Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1min); +} +double GbPolygon3D::getX1Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1max); +} +double GbPolygon3D::getX2Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2s); +} +double GbPolygon3D::getX2Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2min); +} +double GbPolygon3D::getX2Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2max); +} +double GbPolygon3D::getX3Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3s); +} +double GbPolygon3D::getX3Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3min); +} +double GbPolygon3D::getX3Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3max); +} + +/** +* Adds a point to the end of this polygon. Notifies the observers of this 3D polygon. +* @param point the point +*/ +void GbPolygon3D::addPoint(GbPoint3D* point) +{ + //if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon3D.addPoint(): points of 3D polygons have to be 3D points!"); + + this->ps->add(point); + //point.addObserver(this.po); + this->consistent = false; + //super.notifyObservers(); +} +/** +* Adds a number of points to the end of this polygon. Notifies the observers of this 3D polygon. +* @param points the points +*/ +void GbPolygon3D::addPoints(vector<GbPoint3D>& points) +{ + //if((this instanceof GbPolygon3D) && (points.getClass().getComponentType() != GbPoint3D.class)) throw new IllegalArgumentException("GbPolygon3D.addPoints(): points of 3D polygons have to be 3D points!"); + + this->ps->add(points); + //for(int i=0; i<points.length; i++) points[i].addObserver(this.po); + this->consistent = false; + //super.notifyObservers(); +} +/** +* Removes all points from this polygon. Notifies the observers of this 3D polygon. +*/ +void GbPolygon3D::clear() +{ + // delete this->points; + this->ps->clearAndTrim(); + delete this->ps; + + //for(int i=points.length-1; i>=0; i--) points[i].removeObserver(this.po); + this->consistent = false; + //super.notifyObservers(); +} +/** +* Returns a string representation of this 3D polygon. +* @return a string representation of this 3D polygon +*/ +string GbPolygon3D::toString() +{ + stringstream ss; + ss<<"GbPolygon3D["; + ss<<this->size()<<" points"; + ss<<"]"<<endl; + for(int u=0; u<this->size(); u++) + ss<<this->ps->getPoint(u)->toString()<<endl; + + return(ss.str()); +} +/*======================================================================*/ + +void GbPolygon3D::calculateValues() +{ + this->x1s = 0.0; + this->x2s = 0.0; + this->x3s = 0.0; + this->x1min = 0.0; + this->x1max = 0.0; + this->x2min = 0.0; + this->x2max = 0.0; + this->x3min = 0.0; + this->x3max = 0.0; + throw UbException(UB_EXARGS,"should be implemented"); +} +/*======================================================================*/ + + diff --git a/VirtualFluidsBasics/geometry3d/GbPolygon3D.h b/VirtualFluidsBasics/geometry3d/GbPolygon3D.h new file mode 100644 index 0000000000000000000000000000000000000000..e94f2227d1c6ef8fed69dc4d1a5dbe27c2c70c87 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbPolygon3D.h @@ -0,0 +1,285 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbPolygon3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBPOLYGON3D_H +#define GBPOLYGON3D_H + +#include <sstream> +#include <iostream> + + +#include <GbObject3D.h> +#include <GbLine3D.h> +#include <GbTriangle3D.h> +#include <GbSystem3D.h> + +#include <PointerDefinitions.h> + + +/*=========================================================================*/ +//! \class GbPolygon2D +/* */ +//! \brief This Class provides basic 3D polygon objects. + +class GbPolygon3D : public GbObject3D +{ +public: + using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere +private: + /*======================================================================*/ + double x1s ; + double x2s ; + double x3s ; + double x1min; + double x1max; + double x2min; + double x2max; + double x3min; + double x3max; + + std::vector<GbPoint3D> points; + bool consistent; + + GbSystem3D::PointSet3 *ps; + //private PointObserver po = null; + + void init(); + + /*======================================================================*/ + + + /*======================================================================*/ + /* Construcrors */ + /* */ + /* + * Creates an empty 2D polygon. + */ +public: + static int counter; + GbPolygon3D(); + /* + * Creates an empty 2D polygon with the specified capacity. + * @param capacity the initial capacity + */ + GbPolygon3D(int capacity); + /* + * Creates a 2D polygon with the specified points. + * @param points the initial points of the polygon + */ + GbPolygon3D(std::vector<GbPoint3D> &points); + /* + * Creates a 2D polygon as clone of the specified 2D polygon. + * @param polygon the 2D polygon to be cloned + */ + GbPolygon3D(GbPolygon3D *polygon); + + ~GbPolygon3D(); + + /*======================================================================*/ + + + /*======================================================================*/ + /* Methoden */ + /* */ + /* + * Creates a 2D polygon as clone of this 2D polygon. + */ + GbPolygon3D* clone() { return(new GbPolygon3D(this)); } + void finalize() + { + throw UbException(UB_EXARGS,"toDo"); + } + + /* + * Returns the number of points. + * @return the number of points + */ + int size(); + /* + * Returns the number of times this 2D polygon contains the specified point. + * @param point the point + * @return the number of times this 2D polygon contains the specified point + */ + int contains(GbPoint3D *point); + /* + * Returns the number of times this 2D polygon contains a point equal to the specified point. + * @param point the point + * @return the number of times this 2D polygon contains a point equal to the specified point + */ + int containsEqual(GbPoint3D* point); + /* + * Returns true, if this 2D polygon contains the specified line. + * @param point1 the first point + * @param point2 the second point + * @return true, if this 2D polygon contains the specified line + */ + bool containsLine(GbPoint3D* point1, GbPoint3D* point2); + /* + * Returns true, if this 2D polygon contains the specified line. + * @param line the line + * @return true, if this 2D polygon contains the specified line + */ + bool containsLine(GbLine3D* line); + /* + * Returns the first point. + * @return the first point + */ + GbPoint3D* getFirstPoint(); + /* + * Returns the last point. + * @return the last point + */ + GbPoint3D* getLastPoint(); + /* + * Returns the specified point. + * @param index the index + * @return the specified point + * @exception ArrayIndexOutOfBoundsException if the specified index is not valid + */ + GbPoint3D* getPoint(const int& index); + /* + * Returns the points. + * @return the points + */ + std::vector<GbPoint3D> getPoints(); + /* + * Returns the points within the specified rectangle. + * @param p1 the 1st point of the rectangle + * @param p2 the 2nd point of the rectangle + * @return the points within the specified rectangle + */ + std::vector<GbPoint3D> getPoints(GbPoint3D* p1, GbPoint3D* p2); + /* + * Returns the points within the specified rectangle. + * @param p1x1 the 1st x1 coordinate of the rectangle + * @param p1x2 the 1st x2 coordinate of the rectangle + * @param p2x1 the 2nd x1 coordinate of the rectangle + * @param p2x2 the 2nd x2 coordinate of the rectangle + * @return the points within the specified rectangle + */ + std::vector<GbPoint3D> getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3); + /* + * Returns the area of this polygon. + * The area is positive for positive ordered points, otherwise negative. + * @return the area of this polygon + */ + //double getArea() + //{ + // if(!this.consistent) this.calculateValues(); + // return(this.area); + //} + double getX1Centroid(); + double getX1Minimum(); + double getX1Maximum(); + double getX2Centroid(); + double getX2Minimum(); + double getX2Maximum(); + double getX3Centroid(); + double getX3Minimum(); + double getX3Maximum(); + + /* + * Adds a point to the end of this polygon. Notifies the observers of this 2D polygon. + * @param point the point + */ + void addPoint(GbPoint3D* point); + /* + * Adds a number of points to the end of this polygon. Notifies the observers of this 2D polygon. + * @param points the points + */ + void addPoints(std::vector<GbPoint3D>& points); + /* + * Removes all points from this polygon. Notifies the observers of this 2D polygon. + */ + void clear(); + + /* + * Returns true if this 2D polygon equals the specified object. + * Two polygon are equal, if their points are equal. + * <BR>Note that the order of points is recognized! + * @return true if this 2D polygon equals the specified object + * @see GbPoint2D#equals(java.lang.Object) + * @see GbPoint3D#equals(java.lang.Object) + */ + // bool equals(Object object) + // { + // try + // { + // GbPolygon2D polygon = (GbPolygon2D) object; + //int n = this.size(); + + //if(n != polygon.size()) return(false); + //for(int i=0; i<n; i++) if(!this.getPoint(i).equals(polygon.getPoint(i))) return(false); + //return(true); + // } + // catch(Exception e){ return(false); } + // } + std::vector<GbTriangle3D*> getSurfaceTriangleSet() + { + std::cout<<"GbPolygon3D::getSurfaceTriangleSet() - not implemented\n"; + std::vector<GbTriangle3D*> tmp; + return tmp; + } + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3) + { + throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented"); + } + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary) + { + throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented"); + } + bool isCellInsideGbObject3D(double x11,double x21,double x31,double x12,double x22,double x32) { return false; } + + GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D &point2) + { + throw UbException(__FILE__, __LINE__, "GbPolygon3D::createClippedLine3D - not implemented"); + } +/* + * Returns a string representation of this 2D polygon. + * @return a string representation of this 2D polygon + */ + std::string toString(); + + /*======================================================================*/ + /* Private Methoden */ + /* */ + void calculateValues(); + /*======================================================================*/ +}; +/*=========================================================================*/ +#endif + + + + + + diff --git a/VirtualFluidsBasics/geometry3d/GbSystem3D.cpp b/VirtualFluidsBasics/geometry3d/GbSystem3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3afca818f5b917bc8012ad552a894b52b5282b1e --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbSystem3D.cpp @@ -0,0 +1,1218 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbSystem3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbSystem3D.h> +#include <GbPolygon3D.h> +#include <GbCuboid3D.h> + +using namespace std; + +double GbSystem3D::getDistance(const GbPoint3D& p11, const GbPoint3D& p12) +{ + double dx1 = p11.x1 - p12.x1; + double dx2 = p11.x2 - p12.x2; + double dx3 = p11.x3 - p12.x3; + return std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3); +} + +GbPoint3D* GbSystem3D::calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22) +{ + if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1)) return NULL; + if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2)) return NULL; + if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3)) return NULL; + if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return NULL; + if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return NULL; + if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return NULL; + + double a11 = p12.x1 - p11.x1; //..HOW PARAMETERS ARE USED......... + double a12 = p12.x2 - p11.x2; // + double a13 = p12.x3 - p11.x3; // p11 and p12 represent line 1 + double a21 = p21.x1 - p22.x1; // p21 and p22 represent line 2 + double a22 = p21.x2 - p22.x2; // + double a23 = p21.x3 - p22.x3; //.................................. + double b1 = p21.x1 - p11.x1; + double b2 = p21.x2 - p11.x2; + double b3 = p21.x3 - p11.x3; + double d1 = a11*a22 - a12*a21; + double d2 = a11*a23 - a13*a21; + double d3 = a12*a23 - a13*a22; + double t; + + if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return NULL; + if(UbMath::zero(d1)) + { + if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2; + else t = (a23*b2-a22*b3)/d3; + } + else if(UbMath::zero(d2)) + { + if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1; + else t = (a23*b2-a22*b3)/d3; + } + else if(UbMath::zero(d3)) + { + if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1; + else t = (a23*b1-a21*b3)/d2; + } + else return NULL; + + double x1 = p11.x1 + t*a11; + double x2 = p11.x2 + t*a12; + double x3 = p11.x3 + t*a13; + + if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) && + UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) && + UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3) ) return new GbPoint3D(x1, x2, x3); + + return NULL; +} +/*=================================================================*/ +//Line1: p11 -> p12 and Line2: p21 -> p22 +bool GbSystem3D::hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22) +{ + if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1)) return false; + if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2)) return false; + if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3)) return false; + if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return false; + if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return false; + if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return false; + + double a11 = p12.x1 - p11.x1; //..HOW PARAMETERS ARE USED......... + double a12 = p12.x2 - p11.x2; // + double a13 = p12.x3 - p11.x3; // p11 and p12 represent line 1 + double a21 = p21.x1 - p22.x1; // p21 and p22 represent line 2 + double a22 = p21.x2 - p22.x2; // + double a23 = p21.x3 - p22.x3; //.................................. + double b1 = p21.x1 - p11.x1; + double b2 = p21.x2 - p11.x2; + double b3 = p21.x3 - p11.x3; + double d1 = a11*a22 - a12*a21; + double d2 = a11*a23 - a13*a21; + double d3 = a12*a23 - a13*a22; + double t; + + if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return false; + if(UbMath::zero(d1)) + { + if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2; + else t = (a23*b2-a22*b3)/d3; + } + else if(UbMath::zero(d2)) + { + if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1; + else t = (a23*b2-a22*b3)/d3; + } + else if(UbMath::zero(d3)) + { + if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1; + else t = (a23*b1-a21*b3)/d2; + } + else return false; + + double x1 = p11.x1 + t*a11; + double x2 = p11.x2 + t*a12; + double x3 = p11.x3 + t*a13; + + if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) && + UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) && + UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3)) return true; + return false; +} + /*======================================================================*/ +// +// +// /*======================================================================*/ +// /* Private Methoden (Parallelism) */ +// /* */ +bool GbSystem3D::isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22) +{ + double a11 = p12.x1 - p11.x1; //..HOW PARAMETERS ARE USED......... + double a12 = p12.x2 - p11.x2; // + double a13 = p12.x3 - p11.x3; // p11 and p12 represent line 1 + double a21 = p21.x1 - p22.x1; // p21 and p22 represent line 2 + double a22 = p21.x2 - p22.x2; // + double a23 = p21.x3 - p22.x3; //.................................. + + return (UbMath::zero(a11*a22 - a12*a21) && UbMath::zero(a11*a23 - a13*a21) && UbMath::zero(a12*a23 - a13*a22)); +} +/*======================================================================*/ + + +/*======================================================================*/ +/* General Clipping Methods */ +//......................................................................*/ +// +// Method Parameters Result Remarks +// --------- --------------------------------------------- --------- ------------------- +// clip###2D (2D objects to be clipped, 2+2 clipping values) 2D object clipping x1, x2 +// clip###3D (3D objects to be clipped, 2+2 clipping values) 3D object clipping x1, x2 +// clip###3D (3D objects to be clipped, 3+3 clipping values) 3D object clipping x1, x2, x3 +// clip###3D (3D objects to be clipped, 1+1 clipping values) 3D object clipping x3 +// +/*======================================================================*/ +/* Private Methoden (Clipping Lines) */ +/* */ +GbLine3D* GbSystem3D::createClipLine3D(GbPoint3D &pA, GbPoint3D &pB, double x1a, double x2a, double x3a, double x1b, double x2b, double x3b) +{ + GbPoint3D *p1 = new GbPoint3D(pA); + GbPoint3D *p2 = new GbPoint3D(pB); + + if(UbMath::greater(x1a, x1b)) { double x1 = x1a; x1a = x1b; x1b = x1; } + if(UbMath::greater(x2a, x2b)) { double x2 = x2a; x2a = x2b; x2b = x2; } + if(UbMath::greater(x3a, x3b)) { double x3 = x3a; x3a = x3b; x3b = x3; } + + double f; + + /*-------------------------------------------------------------------*/ + /* Schneiden an vorderer Kante */ + /* */ + if(UbMath::less(p1->x3, x3a)) + { + if(UbMath::less(p2->x3, x3a)) { delete p1; delete p2; return NULL; } + + f = (x3a-p1->x3)/(p1->x3-p2->x3); + p1->x1 += (p1->x1-p2->x1)*f; + p1->x2 += (p1->x2-p2->x2)*f; + p1->x3 = x3a; + } + else if(UbMath::less(p2->x3, x3a)) + { + f = (x3a-p2->x3)/(p2->x3-p1->x3); + p2->x1 += (p2->x1-p1->x1)*f; + p2->x2 += (p2->x2-p1->x2)*f; + p2->x3 = x3a; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an unterer Kante */ + /* */ + if(UbMath::less(p1->x2, x2a)) + { + if(UbMath::less(p2->x2, x2a)) { delete p1; delete p2; return NULL; + } + + f = (x2a-p1->x2)/(p1->x2-p2->x2); + p1->x1 += (p1->x1-p2->x1)*f; + p1->x3 += (p1->x3-p2->x3)*f; + p1->x2 = x2a; + } + else if(UbMath::less(p2->x2, x2a)) + { + f = (x2a-p2->x2)/(p2->x2-p1->x2); + p2->x1 += (p2->x1-p1->x1)*f; + p2->x3 += (p2->x3-p1->x3)*f; + p2->x2 = x2a; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an rechter Kante */ + /* */ + if(UbMath::greater(p1->x1, x1b)) + { + if(UbMath::greater(p2->x1, x1b)) { delete p1;delete p2; return NULL;} + + f = (x1b-p1->x1)/(p1->x1-p2->x1); + p1->x2 += (p1->x2-p2->x2)*f; + p1->x3 += (p1->x3-p2->x3)*f; + p1->x1 = x1b; + } + else if(UbMath::greater(p2->x1, x1b)) + { + f = (x1b-p2->x1)/(p2->x1-p1->x1); + p2->x2 += (p2->x2-p1->x2)*f; + p2->x3 += (p2->x3-p1->x3)*f; + p2->x1 = x1b; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an hinterer Kante */ + /* */ + if(UbMath::greater(p1->x3, x3b)) + { + if(UbMath::greater(p2->x3, x3b)) { delete p1;delete p2; return NULL;} + + f = (x3b-p1->x3)/(p1->x3-p2->x3); + p1->x1 += (p1->x1-p2->x1)*f; + p1->x2 += (p1->x2-p2->x2)*f; + p1->x3 = x3b; + } + else if(UbMath::greater(p2->x3, x3b)) + { + f = (x3b-p2->x3)/(p2->x3-p1->x3); + p2->x1 += (p2->x1-p1->x1)*f; + p2->x2 += (p2->x2-p1->x2)*f; + p2->x3 = x3b; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an oberer Kante */ + /* */ + if(UbMath::greater(p1->x2, x2b)) + { + if(UbMath::greater(p2->x2, x2b)) { delete p1;delete p2; return NULL;} + + f = (x2b-p1->x2)/(p1->x2-p2->x2); + p1->x1 += (p1->x1-p2->x1)*f; + p1->x3 += (p1->x3-p2->x3)*f; + p1->x2 = x2b; + } + else if(UbMath::greater(p2->x2, x2b)) + { + f = (x2b-p2->x2)/(p2->x2-p1->x2); + p2->x1 += (p2->x1-p1->x1)*f; + p2->x3 += (p2->x3-p1->x3)*f; + p2->x2 = x2b; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an linker Kante */ + /* */ + if(UbMath::less(p1->x1, x1a)) + { + if(UbMath::less(p2->x1, x1a)) { delete p1;delete p2; return NULL;} + + f = (x1a-p1->x1)/(p1->x1-p2->x1); + p1->x2 += (p1->x2-p2->x2)*f; + p1->x3 += (p1->x3-p2->x3)*f; + p1->x1 = x1a; + } + else if(UbMath::less(p2->x1, x1a)) + { + f = (x1a-p2->x1)/(p2->x1-p1->x1); + p2->x2 += (p2->x2-p1->x2)*f; + p2->x3 += (p2->x3-p1->x3)*f; + p2->x1 = x1a; + } + /*-------------------------------------------------------------------*/ + return new GbLine3D(p1, p2); +} +// /*======================================================================*/ +// /* Private Methoden (Clipping Rectangles) */ +// /* */ +// final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x11, double x12, double x21, double x22) +// { +// GbPoint3D last = null; +// PointSet3 ps = new PointSet3(points); +// boolean flag = false; +// int n = points.length; +// int i; +// double f; +// +// if(n == 0) return(null); +// if(greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; } +// if(greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; } +// +// /*-------------------------------------------------------------------*/ +// /* Schneiden an unterer Kante */ +// /* */ +// if(less(ps.getX2Minimum(), x12)) +// { +// ps.clear(); +// last = points[0]; +// if(less((*points)[0]->x2, x12)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(less((*points)[i]->x2, x12)) +// { +// if(flag) +// { +// f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2); +// ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2); +// ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f)); +// } +// ps.add((*points)[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((less(points[0].x2, x12)) ^ flag)) +// { +// f = (x12-points[0].x2)/(points[0].x2-last->x2); +// ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last->x1)*f, x12, points[0].x3 + (points[0].x3-last->x3)*f)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// /* Schneiden an rechter Kante */ +// /* */ +// if(greater(ps.getX1Maximum(), x21)) +// { +// ps.clear(); +// last = points[0]; +// if(greater(points[0].x1, x21)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(greater((*points)[i]->x1, x21)) +// { +// if(flag) +// { +// f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1); +// ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1); +// ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f)); +// } +// ps.add(points[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((greater(points[0].x1, x21)) ^ flag)) +// { +// f = (x21-points[0].x1)/(points[0].x1-last.x1); +// ps.add(new GbPoint3D(x21, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// /* Schneiden an oberer Kante */ +// /* */ +// if(greater(ps.getX2Maximum(), x22)) +// { +// ps.clear(); +// last = points[0]; +// if(greater(points[0].x2, x22)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(greater((*points)[i]->x2, x22)) +// { +// if(flag) +// { +// f = (x22-(*points)[i]->x2)/(points[i].x2-last.x2); +// ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x22-points[i].x2)/(points[i].x2-last.x2); +// ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f)); +// } +// ps.add(points[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((greater(points[0].x2, x22)) ^ flag)) +// { +// f = (x22-points[0].x2)/(points[0].x2-last.x2); +// ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, x22, points[0].x3 + (points[0].x3-last.x3)*f)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// /* Schneiden an linker Kante */ +// /* */ +// if(less(ps.getX1Minimum(), x11)) +// { +// ps.clear(); +// last = points[0]; +// if(less(points[0].x1, x11)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(less(points[i].x1, x11)) +// { +// if(flag) +// { +// f = (x11-points[i].x1)/(points[i].x1-last.x1); +// ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x11-points[i].x1)/(points[i].x1-last.x1); +// ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f)); +// } +// ps.add(points[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((less(points[0].x1, x11)) ^ flag)) +// { +// f = (x11-points[0].x1)/(points[0].x1-last.x1); +// ps.add(new GbPoint3D(x11, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// GbPolygon3D polygon = new GbPolygon3D(points); +// +// if(n > 2) +// { +// for(i=2; i<n; i++) if(zero(i_TA(points[i-2], points[i-1], points[i]))) polygon.deletePoint(points[i-1]); +// if(zero(i_TA(points[n-2], points[n-1], points[0]))) polygon.deletePoint(points[n-1]); +// if(zero(i_TA(points[n-1], points[0], points[1]))) polygon.deletePoint(points[0]); +// } +// return(polygon); +// } +// final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x13, double x23) +// { +// GbPoint3D last = null; +// PointSet3 ps = new PointSet3(points); +// boolean flag = false; +// int n = points.length; +// int i; +// double f; +// +// if(n == 0) return(null); +// if(greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; } +// +// /*-------------------------------------------------------------------*/ +// /* Schneiden an vorderer Kante */ +// /* */ +// if(less(ps.getX3Minimum(), x13)) +// { +// ps.clear(); +// last = points[0]; +// if(less(points[0].x3, x13)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(less(points[i].x3, x13)) +// { +// if(flag) +// { +// f = (x13-points[i].x3)/(points[i].x3-last.x3); +// ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x13-points[i].x3)/(points[i].x3-last.x3); +// ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13)); +// } +// ps.add(points[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((less(points[0].x3, x13)) ^ flag)) +// { +// f = (x13-points[0].x3)/(points[0].x3-last.x3); +// ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x13)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// /* Schneiden an hinterer Kante */ +// /* */ +// if(greater(ps.getX3Maximum(), x23)) +// { +// ps.clear(); +// last = points[0]; +// if(greater(points[0].x3, x23)) flag = false; +// else +// { +// ps.add(points[0]); +// flag = true; +// } +// for(i=1; i<n; i++) +// { +// if(greater(points[i].x3, x23)) +// { +// if(flag) +// { +// f = (x23-points[i].x3)/(points[i].x3-last.x3); +// ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x23)); +// } +// flag = false; +// } +// else +// { +// if(!flag) +// { +// f = (x23-points[i].x3)/(points[i].x3-last.x3); +// ps.add(new GbPoint3D(points[i].x1 + ((*points)[i]->x1-last.x1)*f, (*points)[i]->x2 + ((*points)[i]->x2-last.x2)*f, x23)); +// } +// ps.add(points[i]); +// flag = true; +// } +// last = points[i]; +// } +// if(!((greater(points[0].x3, x23)) ^ flag)) +// { +// f = (x23-points[0].x3)/(points[0].x3-last.x3); +// ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x23)); +// } +// +// points = ps.getPoints(); +// n = points.length; +// +// if(n == 0) return(null); +// } +// /*-------------------------------------------------------------------*/ +// GbPolygon3D polygon = new GbPolygon3D(points); +// +// return(polygon); +// } +GbPolygon3D* GbSystem3D::clipPolygon3D(vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23) +{ + GbPoint3D last; + PointSet3 ps(points); + bool flag = false; + int n = (int)points.size(); + int i; + double f; + + if(n == 0) return NULL; + if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; } + if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; } + if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; } + + /*-------------------------------------------------------------------*/ + /* Schneiden an vorderer Kante */ + /* */ + if(UbMath::less(ps.getX3Minimum(), x13)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::less((points)[0].x3, x13)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::less((points)[i].x3, x13)) + { + if(flag) + { + f = (x13-(points)[i].x3)/((points)[i].x3-last.x3); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13)); + } + flag = false; + } + else + { + if(!flag) + { + f = (x13-(points)[i].x3)/((points)[i].x3-last.x3); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::less((points)[0].x3, x13)) ^ flag)) + { + f = (x13-(points)[0].x3)/((points)[0].x3-last.x3); + ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x13)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + + /*-------------------------------------------------------------------*/ + /* Schneiden an unterer Kante */ + /* */ + if(UbMath::less(ps.getX2Minimum(), x12)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::less((points)[0].x2, x12)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::less((points)[i].x2, x12)) + { + if(flag) + { + f = (x12-(points)[i].x2)/((points)[i].x2-last.x2); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + flag = false; + } + else + { + if(!flag) + { + f = (x12-(points)[i].x2)/((points)[i].x2-last.x2); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::less((points)[0].x2, x12)) ^ flag)) + { + f = (x12-(points)[0].x2)/((points)[0].x2-last.x2); + ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x12, (points)[0].x3 + ((points)[0].x3-last.x3)*f)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an rechter Kante */ + /* */ + + if(UbMath::greater(ps.getX1Maximum(), x21)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::greater((points)[0].x1, x21)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::greater((points)[i].x1, x21)) + { + if(flag) + { + f = (x21-(points)[i].x1)/((points)[i].x1-last.x1); + ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + flag = false; + } + else + { + if(!flag) + { + f = (x21-(points)[i].x1)/((points)[i].x1-last.x1); + ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::greater((points)[0].x1, x21)) ^ flag)) + { + f = (x21-(points)[0].x1)/((points)[0].x1-last.x1); + ps.add(GbPoint3D(x21, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an hinterer Kante */ + /* */ + if(UbMath::greater(ps.getX3Maximum(), x23)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::greater((points)[0].x3, x23)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::greater((points)[i].x3, x23)) + { + if(flag) + { + f = (x23-(points)[i].x3)/((points)[i].x3-last.x3); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23)); + } + flag = false; + } + else + { + if(!flag) + { + f = (x23-(points)[i].x3)/((points)[i].x3-last.x3); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::greater((points)[0].x3, x23)) ^ flag)) + { + f = (x23-(points)[0].x3)/((points)[0].x3-last.x3); + ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x23)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an oberer Kante */ + /* */ + + if(UbMath::greater(ps.getX2Maximum(), x22)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::greater((points)[0].x2, x22)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::greater((points)[i].x2, x22)) + { + if(flag) + { + f = (x22-(points)[i].x2)/((points)[i].x2-last.x2); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + flag = false; + } + else + { + if(!flag) + { + f = (x22-(points)[i].x2)/((points)[i].x2-last.x2); + ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::greater((points)[0].x2, x22)) ^ flag)) + { + f = (x22-(points)[0].x2)/((points)[0].x2-last.x2); + ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x22, (points)[0].x3 + ((points)[0].x3-last.x3)*f)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + /*-------------------------------------------------------------------*/ + /* Schneiden an linker Kante */ + /* */ + if(UbMath::less(ps.getX1Minimum(), x11)) + { + ps.clear(); + last = (points)[0]; + if(UbMath::less((points)[0].x1, x11)) flag = false; + else + { + ps.add((points)[0]); + flag = true; + } + for(i=1; i<n; i++) + { + if(UbMath::less((points)[i].x1, x11)) + { + if(flag) + { + f = (x11-(points)[i].x1)/((points)[i].x1-last.x1); + ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + + } + flag = false; + } + else + { + if(!flag) + { + f = (x11-(points)[i].x1)/((points)[i].x1-last.x1); + ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f)); + } + ps.add((points)[i]); + flag = true; + } + last = (points)[i]; + } + if(!((UbMath::less((points)[0].x1, x11)) ^ flag)) + { + f = (x11-(points)[0].x1)/((points)[0].x1-last.x1); + ps.add(GbPoint3D(x11, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f)); + } + + points = ps.getPoints(); + n = (int)points.size(); + + if(n == 0) return NULL; + } + /*-------------------------------------------------------------------*/ + return new GbPolygon3D(points); +} +/*=========================================================================*/ +GbCuboid3D* GbSystem3D::clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23) +{ + double r11 = p1.x1; + double r12 = p1.x2; + double r13 = p1.x3; + double r21 = p2.x1; + double r22 = p2.x2; + double r23 = p2.x3; + + if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; } + if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; } + if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; } + if(UbMath::greater(r11, r21)) { double bx = r11; r11 = r21; r21 = bx; } + if(UbMath::greater(r12, r22)) { double by = r12; r12 = r22; r22 = by; } + if(UbMath::greater(r13, r23)) { double bz = r13; r13 = r23; r23 = bz; } + + double m11 = UbMath::greater(x11, r11) ? x11 : r11; + double m12 = UbMath::greater(x12, r12) ? x12 : r12; + double m13 = UbMath::greater(x13, r13) ? x13 : r13; + double m21 = UbMath::greater(x21, r21) ? r21 : x21; + double m22 = UbMath::greater(x22, r22) ? r22 : x22; + double m23 = UbMath::greater(x23, r23) ? r23 : x23; + + if(UbMath::lessEqual(m11, m21) && UbMath::lessEqual(m12, m22) && UbMath::lessEqual(m13, m23)) + return(new GbCuboid3D(new GbPoint3D(m11, m12, m13), new GbPoint3D(m21, m22, m23))); + else + return(NULL); +} + +/*=========================================================================*/ +/*=========================================================================*/ +/*=========================================================================*/ + + +GbSystem3D::PointSet3::PointSet3(int n) +{ + this->init(); + this->points.reserve(n); //reserves n elements! but the size of the vector ist still "0" +} +/*=======================================================*/ +GbSystem3D::PointSet3::PointSet3(const vector<GbPoint3D>& points) +{ + this->init(); + this->add(points); +} +/*=======================================================*/ +void GbSystem3D::PointSet3::add(const GbPoint3D& point) +{ + //is point equal to last point in points then return + if(!this->points.empty() && point.equals(&this->points.back())) return; //WHY??? + + //push point to vector + this->points.push_back(point); + + this->consistent = false; +} +/*=======================================================*/ +void GbSystem3D::PointSet3::addUnequal(const GbPoint3D& point) +{ + if(this->containsEqual(point) > 0) return; + + this->points.push_back(point); + this->consistent = false; +} +/*=======================================================*/ +void GbSystem3D::PointSet3::add(const vector<GbPoint3D>& pointVector) +{ + for(int pos=0; pos<(int)pointVector.size(); pos++ ) + this->points.push_back(pointVector[pos]); + + this->consistent = false; +} +/*=======================================================*/ +void GbSystem3D::PointSet3::insert(const GbPoint3D& point, int index) +{ + if(index<0 || index>=(int)this->points.size()) + throw UbException(UB_EXARGS,"index out of range"); + + //get iterator for index-position + vector<GbPoint3D>::iterator pos=this->points.begin(); + for(int i=1; i<=index; i++) ++pos; + + //insert point + this->points.insert(pos,point); + + this->consistent = false; +} +/*=======================================================*/ +//void delete(GbPoint3D point) +//{ +// for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i); +//} +/*=======================================================*/ +//void delete(int index) +//{ +// int j = this.size - index - 1; +// if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j); +// this.consistent = false; +// this.size--; +//} +/*=======================================================*/ +void GbSystem3D::PointSet3::clear() +{ + //clears points (size==0 but capacity is the old c1) + this->points.clear(); + this->consistent = false; +} +/*=======================================================*/ +void GbSystem3D::PointSet3::clearAndTrim() +{ + //clears points (size==0 AND capacity==0) + this->points.resize(0); + this->consistent = false; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX1Minimum() +{ + if(!this->consistent) this->calculateValues(); + return this->x1min; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX1Maximum() +{ + if(!this->consistent) this->calculateValues(); + return this->x1max; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX2Minimum() +{ + if(!this->consistent) this->calculateValues(); + return this->x2min; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX2Maximum() +{ + if(!this->consistent) this->calculateValues(); + return this->x2max; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX3Minimum() +{ + if(!this->consistent) this->calculateValues(); + return this->x3min; +} +/*=======================================================*/ +double GbSystem3D::PointSet3::getX3Maximum() +{ + if(!this->consistent) this->calculateValues(); + return this->x3max; +} +/*=======================================================*/ +int GbSystem3D::PointSet3::contains(GbPoint3D* point) +{ + //returns number of points which has the same adress (this should be 0 or 1!!!) + int n=0; + + for(int pos=(int)this->points.size()-1; pos>=0; pos--) + if(&this->points[pos]==point) n++; + + return n; +} +/*=======================================================*/ +int GbSystem3D::PointSet3::containsEqual(const GbPoint3D& point) +{ + //returns number of points which have the same coordinates with point (could be 0,1 or even more) + int n=0; + + for(int pos=(int)this->points.size()-1; pos>=0; pos--) + if(this->points[pos].equals(&point)) n++; + + return n; +} +/*=======================================================*/ +bool GbSystem3D::PointSet3::containsLine(GbPoint3D *point1, GbPoint3D *point2) +{ + //returns true if pointset has c2 in "this->points"vector neighboured points + //wich have the same adress as point1 or point2 + vector<GbPoint3D>::iterator pos1=this->points.begin(); + vector<GbPoint3D>::iterator pos2; + + for(pos2=pos1++; pos2!=this->points.end(); ++pos2) + { + if (&(*pos1)==point1 && &(*pos2)==point2) return true; + else if(&(*pos1)==point2 && &(*pos2)==point1) return true; + + pos1=pos2; + } + + return false; +} +/*=======================================================*/ +bool GbSystem3D::PointSet3::containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2) +{ + //returns true if pointset has c2 in "this->points"vector neighboured points + //wich have the same coordinates as point1 or point2 + vector<GbPoint3D>::iterator pos1=this->points.begin(); + vector<GbPoint3D>::iterator pos2; + + for(pos2=pos1++; pos2!=this->points.end(); ++pos2) + { + if ((*pos1).equals(&point1) && (*pos2).equals(&point2)) return true; + else if((*pos1).equals(&point2) && (*pos2).equals(&point1)) return true; + + pos1=pos2; + } + + return false; +} +/*=======================================================*/ +GbPoint3D* GbSystem3D::PointSet3::getPoint(int index) +{ + if(index<0 || index>=(int)this->points.size()) throw UbException(UB_EXARGS,"index out of range"); + return &(this->points)[index]; +} +/*=======================================================*/ +GbPoint3D* GbSystem3D::PointSet3::getFirstPoint() +{ + return &(this->points.front()); +} +/*=======================================================*/ +GbPoint3D* GbSystem3D::PointSet3::getLastPoint() +{ + return &(this->points.back()); +} +/*=======================================================*/ +int GbSystem3D::PointSet3::size() +{ + return (int)this->points.size(); +} +/*=======================================================*/ +vector<GbPoint3D> GbSystem3D::PointSet3::getPoints() +{ + //is this right? it's another effect as at GbPoint3D* getNode(index)!!! + //or do we want to have the next uncommented getPoints() funktion + return this->points; +} +///*=======================================================*/ +//vector<GbPoint3D*> GbSystem3D::PointSet3::getPoints() +//{ +// vector<GbPoint3D*> tmp; +// for(int pos=0; pos<(int)this->points.size();pos++) tmp.push_back(&this->points[pos]); +// +// return tmp; +//} +/*=======================================================*/ +void GbSystem3D::PointSet3::calculateValues() +{ + if(this->points.empty()) + { + this->x1min = this->x2min = this->x3min = 0.0; + this->x1max = this->x2max = this->x3max = 0.0; + } + else + { + this->x1min = (this->points)[0].x1; + this->x1max = (this->points)[0].x1; + this->x2min = (this->points)[0].x2; + this->x2max = (this->points)[0].x2; + this->x3min = (this->points)[0].x3; + this->x3max = (this->points)[0].x3; + + for(int i=(int)this->points.size()-1; i>0; --i) + { + if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1; + if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1; + if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2; + if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2; + if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3; + if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3; + } + } + this->consistent = true; +} + + + diff --git a/VirtualFluidsBasics/geometry3d/GbSystem3D.h b/VirtualFluidsBasics/geometry3d/GbSystem3D.h new file mode 100644 index 0000000000000000000000000000000000000000..57955d6b9f582b4315de114be7866f733bb47134 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbSystem3D.h @@ -0,0 +1,422 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbSystem3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBSYSTEM3D_H +#define GBSYSTEM3D_H + +#include <iostream> +#include <cmath> +#include <vector> + +#include <GbPoint3D.h> +#include <GbObject3D.h> +#include <basics/utilities/UbMath.h> +#include <basics/writer/WbWriter.h> + +class GbPolygon3D; +class GbCuboid3D; +class GbLine3D; + +namespace GbSystem3D +{ + extern double getDistance(const GbPoint3D& p11, const GbPoint3D& p12); + extern GbPoint3D* calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22); + extern GbPolygon3D* clipPolygon3D(std::vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23); + extern GbLine3D* createClipLine3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23); + extern bool hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22); + extern bool isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22); + extern GbCuboid3D* clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23); + + /*========================================================================================*/ + inline static std::string writeGeoObject(GbObject3D* gbobject, const std::string& filename, WbWriter* writer) + { + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt3> triangles; + gbobject->addSurfaceTriangleSet(nodes, triangles); + + std::string outFilename = writer->writeTriangles(filename,nodes,triangles); + return outFilename; + } + //the same as before + /*========================================================================================*/ + inline static std::string writeGeoObject(SPtr<GbObject3D> gbobject, const std::string& filename, WbWriter* writer) + { + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt3> triangles; + gbobject->addSurfaceTriangleSet(nodes, triangles); + + std::string outFilename = writer->writeTriangles(filename,nodes,triangles); + return outFilename; + } + /*========================================================================================*/ + inline static std::vector< std::string > writeGeoObject(GbObject3D* gbobject, const std::string& filename, std::vector< WbWriter* > writer ) + { + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt3> triangles; + gbobject->addSurfaceTriangleSet(nodes, triangles); + + std::vector< std::string > outFilenames; + for(std::size_t i=0; i<writer.size(); ++i) + outFilenames.push_back( writer[i]->writeTriangles(filename,nodes,triangles) ); + return outFilenames; + } + /*========================================================================================*/ + inline static std::string writeGeoObjects(std::vector< GbObject3D* > gbobjects, const std::string& filename, WbWriter* writer) + { + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt3> triangles; + + for(std::size_t i=0; i<gbobjects.size(); ++i) + { + //std::cout<<i<<", "<<gbobjects[i]<<std::endl; + gbobjects[i]->addSurfaceTriangleSet(nodes, triangles); + } + + std::string outFilename = writer->writeTriangles(filename,nodes,triangles); + return outFilename; + } + /*========================================================================================*/ + + ////////////////////////////////////////////////////////////////////////// + class PointSet3 + { + public: + PointSet3(int n); + PointSet3(const std::vector<GbPoint3D>& points); + ~PointSet3(){} + void add(const GbPoint3D& point); + void addUnequal(const GbPoint3D& point); + void add(const std::vector<GbPoint3D>& p); + int contains(GbPoint3D* point); + void insert(const GbPoint3D& point, int index); + void clear(); + void clearAndTrim(); + int containsEqual(const GbPoint3D& point); + bool containsLine(GbPoint3D* point1, GbPoint3D* point2); + bool containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2); + double getX1Minimum(); + double getX1Maximum(); + double getX2Minimum(); + double getX2Maximum(); + double getX3Minimum(); + double getX3Maximum(); + void calculateValues(); + int size(); + GbPoint3D* getPoint(int index); + GbPoint3D* getFirstPoint(); + GbPoint3D* getLastPoint() ; + std::vector<GbPoint3D> getPoints(); + + private: + double x1min; + double x1max; + double x2min; + double x2max; + double x3min; + double x3max; + bool consistent; + std::vector<GbPoint3D> points; + + void init() + { + consistent = false; + x1min = x2min = x3min = 0.0; + x1max = x2max = x3max = 0.0; + } + }; + /*=================================================================*/ + class OldPointSet3 + { + private: + int sizet; + double x1min; + double x1max; + double x2min; + double x2max; + double x3min; + double x3max; + bool consistent; + std::vector<GbPoint3D> points; + + void init() + { + sizet = 0; + x1min = 0.0; + x1max = 0.0; + x2min = 0.0; + x2max = 0.0; + x3min = 0.0; + x3max = 0.0; + consistent = false; + //points = NULL; + }; + + public: + OldPointSet3(int n) + { + this->init(); + this->points.resize(n); + } + OldPointSet3(std::vector<GbPoint3D> &points) + { + this->init(); + this->points.resize(0);//, NULL); + this->add(points); + }; + ~OldPointSet3() + { + // delete points; + }; + void add(GbPoint3D point) + { + if(this->sizet>0 && point.equals(&(this->points)[this->sizet-1])) return; + if(this->sizet == (int)this->points.size()) + { + std::vector<GbPoint3D> a; + a.resize(1+(this->sizet<<1)); + for(int u=0; u<this->sizet; u++) { (a)[u] = (points)[u]; } + this->points = a; + } + (this->points)[this->sizet] = point; + this->consistent = false; + this->sizet++; + } + void addUnequal(GbPoint3D *point) + { + if(this->containsEqual(point) > 0) return; + if(this->sizet == (int)this->points.size()) + { + std::vector<GbPoint3D> a; + a.resize(1+(this->sizet<<1)); + for(int u=0; u<this->sizet; u++) { (a)[u] = (points)[u]; } + this->points = a; + } + (this->points)[this->sizet] = point; + this->consistent = false; + this->sizet++; + } + void add(std::vector<GbPoint3D> &p) + { + if(this->sizet+p.size() >= this->points.size()) + { + std::vector<GbPoint3D> a; + a.resize(this->sizet+p.size()); + for(int u=0; u<(int)this->points.size(); u++) { (a)[u] = (this->points)[u]; } + this->points = a; + } + int u = this->sizet;// (int)this->points->size(); + for(int b=0; b<(int)p.size(); b++) (this->points)[u++] = (p)[b]; + //u = this->sizet; + //for(int b=0; b<(int)p->size(); b++) + // cout<<(this->points)[u++].toString()<<endl; + this->consistent = false; + this->sizet += (int)p.size(); + }; + // void insert(GbPoint3D *point, int index) + // { + // if(this.size == this.points.length) + // { + // GbPoint3D a[] = new GbPoint3D[1+(this.size<<1)]; + // System.arraycopy(this.points, 0, a, 0, this.size); + // this.points = a; + // } + // System.arraycopy(this.points, index, this.points, index+1, this.size-index); + // this.points[index] = point; + // this.consistent = false; + // this.size++; + // } + // void delete(GbPoint3D point) + // { + // for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i); + // } + // void delete(int index) + // { + // int j = this.size - index - 1; + // if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j); + // this.consistent = false; + // this.size--; + // } + void clear() + { + this->sizet = 0; + this->consistent = false; + } + void clearAndTrim() + { + this->sizet = 0; + this->points.resize(0); + this->consistent = false; + } + + double getX1Minimum() + { + if(!this->consistent) this->calculateValues(); + return(this->x1min); + } + double getX1Maximum() + { + if(!this->consistent) this->calculateValues(); + return(this->x1max); + } + double getX2Minimum() + { + if(!this->consistent) this->calculateValues(); + return(this->x2min); + } + double getX2Maximum() + { + if(!this->consistent) this->calculateValues(); + return(this->x2max); + } + double getX3Minimum() + { + if(!this->consistent) this->calculateValues(); + return(this->x3min); + } + double getX3Maximum() + { + if(!this->consistent) this->calculateValues(); + return(this->x3max); + } + void calculateValues() + { + this->x1min = 0.0; + this->x1max = 0.0; + this->x2min = 0.0; + this->x2max = 0.0; + this->x3min = 0.0; + this->x3max = 0.0; + this->consistent = true; + + if(this->sizet == 0) return; + + this->x1min = (this->points)[0].x1; + this->x1max = (this->points)[0].x1; + this->x2min = (this->points)[0].x2; + this->x2max = (this->points)[0].x2; + this->x3min = (this->points)[0].x3; + this->x3max = (this->points)[0].x3; + + for(int i=this->sizet-1; i>0; i--) + { + if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1; + if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1; + if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2; + if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2; + if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3; + if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3; + } + }; + + int contains(GbPoint3D *point) + { + int n = 0; + for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point) n++; + return(n); + }; + int containsEqual(GbPoint3D *point) + { + int n = 0; + for(int i=this->sizet-1; i>=0; i--) if((this->points)[i].equals(point)) n++; + return(n); + } + bool containsLine(GbPoint3D *point1, GbPoint3D *point2) + { + for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point1) + { + if(i == 0) + { + if(&(this->points)[i+1] == point2) return(true); + if(&(this->points)[this->sizet-1] == point2) return(true); + } + else if(i == this->sizet-1) + { + if(&(this->points)[0] == point2) return(true); + if(&(this->points)[i-1] == point2) return(true); + } + else + { + if(&(this->points)[i+1] == point2) return(true); + if(&(this->points)[i-1] == point2) return(true); + } + } + return(false); + }; + // boolean containsEqualLine(GbPoint2D point1, GbPoint2D point2) + // { + // for(int i=this.size-1; i>=0; i--) if(this.points[i].equals(point1)) + // { + // if(i == 0) + // { + // if(this.points[i+1].equals(point2)) return(true); + // if(this.points[this.size-1].equals(point2)) return(true); + // } + // else if(i == this.size-1) + // { + // if(this.points[0].equals(point2)) return(true); + // if(this.points[i-1].equals(point2)) return(true); + // } + // else + // { + // if(this.points[i+1].equals(point2)) return(true); + // if(this.points[i-1].equals(point2)) return(true); + // } + // } + // return(false); + // } + GbPoint3D *getPoint(int index) + { + return(&(this->points)[index]); + } + GbPoint3D *getFirstPoint() + { + return(&(this->points)[0]); + } + GbPoint3D *getLastPoint() { return(&(this->points)[this->sizet-1]); } + int size() { return(this->sizet); } + std::vector<GbPoint3D> getPoints() + { + points.resize(sizet); + return points; + //int l = this->sizet; + //if(l > 1 && (this->points)[0].equals(&(this->points)[l-1])) l--; + + //vector<GbPoint3D*> *a = new vector<GbPoint3D*>; + //a->resize(l, NULL); + //for(int u=0; u<l; u++) { (*a)[u] = &((points)[u]); } + //return(a); + } + }; + /*=================================================================*/ +} + +#endif //GBSYSTEM3D_H diff --git a/VirtualFluidsBasics/geometry3d/GbTriangle3D.cpp b/VirtualFluidsBasics/geometry3d/GbTriangle3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9024aaf40f67f226392e15a9cfc6470d55ca39a --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbTriangle3D.cpp @@ -0,0 +1,1130 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbTriangle3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbTriangle3D.h> +#include <GbSystem3D.h> +#include <GbLine3D.h> +#include <GbCuboid3D.h> + +#include <basics/utilities/UbMath.h> + +using namespace std; + +GbTriangle3D::GbTriangle3D() +{ + this->init(); + this->consistent = false; +} +/*======================================================================*/ +/* +* Creates an empty 2D triangle with the specified points. +* @param point1 the 1st point +* @param point2 the 2nd point +* @param point3 the 3nd point +*/ +GbTriangle3D::GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3) +{ + this->init(); + this->points[0] = point1; + this->points[1] = point2; + this->points[2] = point3; + + this->calculateNormal(); + this->consistent = false; + + this->points[0]->addObserver(this); + this->points[1]->addObserver(this); + this->points[2]->addObserver(this); + + //this.po = new PointObserver(this); + //this.points[0].addObserver(this.po); + //this.points[1].addObserver(this.po); + //this.points[2].addObserver(this.po); +} +/*======================================================================*/ +/* +* Creates a 3D triangle as clone of the specified 2D triangle. +* @param triangle the 3D triangle to be cloned +*/ +GbTriangle3D::GbTriangle3D(GbTriangle3D* triangle) +{ + this->init(); + this->points[0] = triangle->points[0]->clone(); + this->points[1] = triangle->points[1]->clone(); + this->points[2] = triangle->points[2]->clone(); + + this->consistent = false; + this->calculateNormal(); + this->calculateValues(); +} +/*======================================================================*/ +GbTriangle3D::~GbTriangle3D() +{ + if(this->points[0]) this->points[0]->removeObserver(this); + if(this->points[1]) this->points[1]->removeObserver(this); + if(this->points[2]) this->points[2]->removeObserver(this); +} +/*======================================================================*/ +void GbTriangle3D::deletePoints() +{ + if(points[0]) { delete points[0]; points[0]=NULL;} + if(points[1]) { delete points[1]; points[1]=NULL;} + if(points[2]) { delete points[2]; points[2]=NULL;} +} + +/*======================================================================*/ +/* Methoden */ +/* */ +/* +* Creates a 3D triangle as clone of this 3D triangle. +*/ +GbTriangle3D* GbTriangle3D::clone() +{ + return(new GbTriangle3D(this)); +} +/*======================================================================*/ +/* +* Returns the number of times this 2D triangle contains the specified point. +* @param point the point +* @return the number of times this 2D triangle contains the specified point +*/ +int GbTriangle3D::contains(GbPoint3D* point) +{ + int n = 0; + for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++; + return(n); +} +/*======================================================================*/ +/* +* Returns the number of times this 2D triangle contains a point equal to the specified point. +* @param point the point +* @return the number of times this 2D triangle contains a point equal to the specified point +*/ +int GbTriangle3D::containsEqual(GbPoint3D* point) +{ + int n = 0; + for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++; + return(n); +} +/*======================================================================*/ +/* +* Returns the specified point. +* @param index the index (must be 0, 1, or 2) +* @return the specified point +* @exception ArrayIndexOutOfBoundsException if the specified index is not valid +*/ +GbPoint3D* GbTriangle3D::getPoint(const int& index) +{ + if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: "); + return((this->points[index])); +} +/*======================================================================*/ +vector<GbPoint3D> GbTriangle3D::getPoints() +{ + vector<GbPoint3D> p(3); + p[0] = *(points[0]); + p[1] = *(points[1]); + p[2] = *(points[2]); + return p; + // + //vector<GbPoint3D> p(3);// = new vector<GbPoint3D*>; + //p.resize(3);//, NULL); + //p[0] = this->points[0]; + //p[1] = this->points[1]; + //p[2] = this->points[2]; + //return(p); +} +/*======================================================================*/ +/* +* Returns the area of this triangle. +* The area is positive for positive ordered points, otherwise negative. +* @return the area of this triangle +*/ +double GbTriangle3D::getArea() +{ + if(!this->consistent) this->calculateValues(); + // throw UbException(UB_EXARGS,"not correct calculated ..."); + return(this->area); +} +/* +* Returns the centroid x1 coordinate of this triangle. +* @return the centroid x1 coordinate of this triangle +*/ +double GbTriangle3D::getX1Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1s); +} +/* +* Returns the minimum x1 coordinate of this triangle. +* @return the minimum x1 coordinate of this triangle +*/ +double GbTriangle3D::getX1Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1min); +} +/* +* Returns the maximum x1 coordinate of this triangle. +* @return the maximum x1 coordinate of this triangle +*/ +double GbTriangle3D::getX1Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x1max); +} +/* +* Returns the centroid x2 coordinate of this triangle. +* @return the centroid x2 coordinate of this triangle +*/ +double GbTriangle3D::getX2Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2s); +} +/* +* Returns the minimum x2 coordinate of this triangle. +* @return the minimum x2 coordinate of this triangle +*/ +double GbTriangle3D::getX2Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2min); +} +/* +* Returns the maximum x2 coordinate of this triangle. +* @return the maximum x2 coordinate of this triangle +*/ +double GbTriangle3D::getX2Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x2max); +} +double GbTriangle3D::getX3Centroid() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3s); +} +double GbTriangle3D::getX3Minimum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3min); +} +double GbTriangle3D::getX3Maximum() +{ + if(!this->consistent) this->calculateValues(); + return(this->x3max); +} + +/* +* Sets the specified point. +* @param point the point +* @param index the index (must be 0, 1, or 2) +* @exception ArrayIndexOutOfBoundsException if the specified index is not valid +*/ +void GbTriangle3D::setPoint(GbPoint3D* point, int index) +{ + if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: "); + this->points[index] = point; + this->consistent = false; + this->calculateNormal(); +} + +/* +* Returns the surface triangle set with new nodes !!! +* @returns the surface triangle set with new nodes !!! +*/ +vector<GbTriangle3D*> GbTriangle3D::getSurfaceTriangleSet() +{ + vector<GbTriangle3D*> triangles; + + triangles.push_back(new GbTriangle3D(new GbPoint3D(getPoint1()),new GbPoint3D(getPoint2()),new GbPoint3D(getPoint3()))); + + return triangles; +} + + +/* +* Returns the string representation of the triangle +* @returns the string representation of the triangle +*/ + +string GbTriangle3D::toString() +{ + stringstream ss; + ss<<"GbTriangle3D[area="; + ss<<this->getArea(); + + ss<<", x1s="<<this->x1s; + ss<<", x2s="<<this->x2s; + ss<<", x3s="<<this->x3s; + ss<<", x1min="<<this->x1min; + ss<<", x1max="<<this->x1max; + ss<<", x2min="<<this->x2min; + ss<<", x2max="<<this->x2max; + ss<<", x3min="<<this->x3min; + ss<<", x3max="<<this->x3max; + ss<<", points1="<<this->points[0]->toString(); + ss<<", points2="<<this->points[1]->toString(); + ss<<", points3="<<this->points[2]->toString(); + ss<<"]"; + return((ss.str()).c_str()); +} +/*======================================================================*/ +double GbTriangle3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3) +{ + //e1 = v1 - v0 + double e1x1 = this->points[1]->x1-this->points[0]->x1; + double e1x2 = this->points[1]->x2-this->points[0]->x2; + double e1x3 = this->points[1]->x3-this->points[0]->x3; + + //e2 = v2 - v0 + double e2x1 = this->points[2]->x1-this->points[0]->x1; + double e2x2 = this->points[2]->x2-this->points[0]->x2; + double e2x3 = this->points[2]->x3-this->points[0]->x3; + + //p = d x e2 + double px1 = rx2*e2x3 - rx3*e2x2; + double px2 = rx3*e2x1 - rx1*e2x3; + double px3 = rx1*e2x2 - rx2*e2x1; + + //a = e1 dot p + double a = e1x1*px1 + e1x2*px2 + e1x3*px3; + if(fabs(a)<1.E-10) return -1.0; + double f = 1.0/a; + + //s = o - v0 + double sx1 = x1 - this->points[0]->x1; + double sx2 = x2 - this->points[0]->x2; + double sx3 = x3 - this->points[0]->x3; + + //u = f * ( s dot p) + double u = f * ( sx1*px1 + sx2*px2 + sx3*px3 ); + if(u<-1.E-10 || u>1.0+1.E-10) return -1.0; + + //q = s x e1 + double qx1 = sx2*e1x3 - sx3*e1x2; + double qx2 = sx3*e1x1 - sx1*e1x3; + double qx3 = sx1*e1x2 - sx2*e1x1; + + //v = f*(e2 dot q) + double v = f * (rx1*qx1 + rx2*qx2 + rx3*qx3); + if(v<-1.E-10 || (u+v)>1.0+1.E-10) return -1.0; + + //t = f * (e2 dot q) + return f * (e2x1*qx1 + e2x2*qx2 + e2x3*qx3); +} + +/*===========================================================*/ + +GbLine3D* GbTriangle3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2) +{ + GbPoint3D *result = this->calculateIntersectionPoints3D(&point1, &point2); + if(!result) return NULL; + + return new GbLine3D(result, new GbPoint3D(point2)); + + //return GbSystem::createClipLine3D(point1, point2, + //p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(), + //p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() ); +} + +//von Navodit ... +/*===========================================================*/ +GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbLine3D* line) +{ + return this->calculateIntersectionPoints3D(line->getPoint1(), line->getPoint2()); +} +/*===========================================================*/ +GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2) +{ + GbVector3D Point1(linePoint1->x1, linePoint1->x2, linePoint1->x3); + GbVector3D Point2(linePoint2->x1, linePoint2->x2, linePoint2->x3); + GbVector3D direction = Point2-Point1; + GbVector3D GbPoint3D1(this->getPoint1()->x1,this->getPoint1()->x2,this->getPoint1()->x3); + GbVector3D GbPoint3D2(this->getPoint2()->x1,this->getPoint2()->x2,this->getPoint2()->x3); + GbVector3D GbPoint3D3(this->getPoint3()->x1,this->getPoint3()->x2,this->getPoint3()->x3); + GbVector3D V2V1 = GbPoint3D2-GbPoint3D1; + GbVector3D V3V1 = GbPoint3D3-GbPoint3D1; + GbVector3D V2V1V3V1 = V2V1.Cross(V3V1); + V2V1V3V1.Normalize(); + GbVector3D Normal = V2V1V3V1; + + double d = -Normal.Dot(GbPoint3D1); + double denom = Normal.Dot(direction); + + if (UbMath::zero(denom)) return NULL; //line does not intersect the plane of the triangle ! + else + { + double mu = -1.*(d + Point1.Dot(Normal))/denom; //mu = -(d+ Normal.Point1)/denom + + // GbVector3D p1 = Point2-Point1; + // GbVector3D p2 = p1*mu; + // GbVector3D p3 = Point1+p2; + GbVector3D point = Point1 + mu*(Point2 -Point1); + + if (mu<0.0 || mu>1.0) return NULL; // Point of intersection of line and plane does not lie on the triangle + else + { + //Test whether Point lies inside the triangle or not + bool test=true; + GbVector3D a = GbPoint3D1-point; + GbVector3D b = GbPoint3D2-point; + GbVector3D c = GbPoint3D3-point; + GbVector3D ab = a.Cross(b); + GbVector3D bc = b.Cross(c); + GbVector3D ca = c.Cross(a); + GbVector3D Q1 = ab*0.5; + GbVector3D Q2 = bc*0.5; + GbVector3D Q3 = ca*0.5; + GbVector3D Q1Q2 = Q1+Q2; + GbVector3D Q = Q1Q2+Q3; + + if (UbMath::less(Q.Dot(Q1), 0.0)) test = false; + if (UbMath::less(Q.Dot(Q2), 0.0)) test = false; + if (UbMath::less(Q.Dot(Q3), 0.0)) test = false; + + if (test == true) return (new GbPoint3D(point.X1(), point.X2(), point.X3())); + else return NULL; + } + } +} + +/** +* Returns the distance between the 3D triangle and the specified 3D Point +* @param point the 3D point from whom the distance is to be calculated +* @return the distance of the specified point from the triangle +*/ +double GbTriangle3D::calculateDistanceToPoint3D(GbPoint3D *point) +{ + return this->calculateDistanceToPoint3D(point->x1, point->x2, point->x3); +} +/*=======================================================================*/ +double GbTriangle3D::calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3) +{ + // + //throw UbException(UB_EXARGS,"Ich glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's"); + cout<<"??? ch glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's"<<endl; + GbVector3D P0(x1, x2, x3); + GbVector3D P1(this->points[0]->x1, this->points[0]->x2, this->points[0]->x3); + GbVector3D P2(this->points[1]->x1, this->points[1]->x2, this->points[1]->x3); + GbVector3D P3(this->points[2]->x1, this->points[2]->x2, this->points[2]->x3); + + //Determine normal to triangle + GbVector3D Normal = (P1-P2).Cross(P1-P3); + double alpha = UbMath::ACos((P1-P0).Dot(Normal)/((P1-P0).Length()*Normal.Length())); + + double P0P0dash = (P0-P1).Length()*cos(alpha); + Normal.Normalize(); + GbVector3D Projection = Normal*(-P0P0dash); + + GbVector3D P0dash = P0+Projection; + + //Check if point P0dash lies within the triangle P1P2P3. + bool test = false; + if ( ((P1-P0).Cross(P2-P0)).Dot(Normal) > 0 ) test = true; + if ( ((P2-P0).Cross(P3-P0)).Dot(Normal) > 0 ) test = true; + if ( ((P3-P0).Cross(P1-P0)).Dot(Normal) > 0 ) test = true; + + if (test == true) return (P0-P0dash).Length(); + else + // Determine the distance of point P0 from all edges and vertices and return the minimum distance + { + double dP0P1 = (P0-P1).Length(); //Distance of Point P0 from Point P1 + double dP0P2 = (P0-P2).Length(); //Distance of Point P0 from Point P2 + double dP0P3 = (P0-P3).Length(); //Distance of Point P0 from Point P3 + + GbVector3D MP1P2 = P2-P1; //Direction vector for line P1P2 + GbVector3D MP2P3 = P3-P2; //Direction vector for line P2P3 + GbVector3D MP3P1 = P1-P3; //Direction vector for line P3P1 + + double tP1P2 = MP1P2.Dot(P0-P1) / MP1P2.Dot(MP1P2); + double tP2P3 = MP2P3.Dot(P0-P2) / MP2P3.Dot(MP2P3); + double tP3P1 = MP3P1.Dot(P0-P3) / MP3P1.Dot(MP3P1); + + double dP1P2 = (P0-(P1+(MP1P2*tP1P2))).Length(); //Distance of Point P0 from line P1P2 + double dP2P3 = (P0-(P2+(MP2P3*tP2P3))).Length(); //Distance of Point P0 from line P2P3 + double dP3P1 = (P0-(P3+(MP3P1*tP3P1))).Length(); //Distance of Point P0 from line P3P1 + + double distanceP0[6]; //Array to store all the distances from Point P0 + distanceP0[0] = dP0P1; + distanceP0[1] = dP0P2; + distanceP0[2] = dP0P3; + distanceP0[3] = dP1P2; + distanceP0[4] = dP2P3; + distanceP0[5] = dP3P1; + + double d = 0.0; + //Find the minimum distance from Point P0 + for (int i=0; i<6; i++) + { + if(distanceP0[i]<d) d = distanceP0[i]; + } + return d; + } +} +/** +* Returns the normalized distance between the 3D triangle and the specified 3D Point +* copied from Benjamin A. +* @param point the 3D point from whom the distance is to be calculated +* @return the distance of the specified point from the triangle +*/ +double GbTriangle3D::calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, + const double& x2, const double& y2, const double& z2) +{ + //face* pf + double xa, xb, xc, ya, yb, yc, za, zb, zc; + //double xp, yp, zp; + double tt=0, xi=0, eta=0; + double zaehler, nenner; + double wurzel3 = sqrt(3.); + + //Weltkoordinaten der Dreiecke + xa = this->points[0]->x1; + xb = this->points[1]->x1; + xc = this->points[2]->x1; + + ya = this->points[0]->x2; + yb = this->points[1]->x2; + yc = this->points[2]->x2; + + za = this->points[0]->x3; + zb = this->points[1]->x3; + zc = this->points[2]->x3; + + //Shape-Funktionen zum Berechnen der Schnittpunkte + zaehler = + static_cast<double>(((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1 + +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa + +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zc+zb)*ya+(yc-1.0*yb)*za + +zc*yb-1.0*zb*yc)*x2+((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2 + +((-1.0*yc+yb)*xa+(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z2+(2.0*zb*yc-2.0*zc*yb)*xa + +(2.0*xb*zc-2.0*xc*zb)*ya+(-2.0*xb*yc+2.0*xc*yb)*za); + nenner = + static_cast<double>((((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1 + +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa + +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zb+zc)*ya+(-1.0*yc+yb)*za-1.0*zc*yb+zb*yc) + *x2+((-1.0*zc+zb)*xa+(-1.0*xb+xc)*za+xb*zc-1.0*xc*zb)*y2+((yc-1.0*yb)*xa+(xb + -1.0*xc)*ya+xc*yb-1.0*xb*yc)*z2)); + if( UbMath::greater(nenner, 0.0) ) tt = zaehler/nenner; + else tt=-999.; + + zaehler = + static_cast<double>(((-2.0*zc+za+zb)*y2+(-1.0*yb-1.0*ya+2.0*yc)*z2+zc*ya + -1.0*zb*yc+zc*yb-1.0*za*yc)*x1+((-1.0*za+2.0*zc-1.0*zb)*x2+(xa-2.0*xc+xb)*z2 + -1.0*xa*zc-1.0*xb*zc+xc*za+xc*zb)*y1+((-2.0*yc+ya+yb)*x2+(-1.0*xa-1.0*xb+2.0*xc) + *y2-1.0*xc*yb+xa*yc+xb*yc-1.0*xc*ya)*z1+(zb*yc-1.0*zc*ya-1.0*zc*yb+za*yc) + *x2+(-1.0*xc*za+xb*zc+xa*zc-1.0*xc*zb)*y2+(xc*yb-1.0*xa*yc-1.0*xb*yc+xc*ya)*z2); + nenner = + static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1 + +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc) + *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2 + +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa + +(xc-1.0*xb)*ya+xb*yc-1.0*xc*yb)*z2)); + if( UbMath::greater(nenner, 0.0) ) xi = zaehler/nenner; + else xi=-999.; + + zaehler = + static_cast<double>(((za-1.0*zb)*y2+(-1.0*ya+yb)*z2-1.0*za*yb+zb*ya)*x1+ + ((-1.0*za+zb)*x2+(xa-1.0*xb)*z2-1.0*xa*zb+xb*za)*y1+((ya-1.0*yb)*x2+(xb-1.0*xa) + *y2+xa*yb-1.0*xb*ya)*z1+(-1.0*zb*ya+za*yb)*x2+(-1.0*xb*za+xa*zb)*y2 + +(-1.0*xa*yb+xb*ya)*z2); + nenner = + static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1 + +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc) + *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2 + +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa+(xc-1.0*xb) + *ya+xb*yc-1.0*xc*yb)*z2)); + if ( UbMath::greater(nenner, 0.0) ) eta = static_cast<double>((zaehler/nenner)*wurzel3*-1.); + else eta=-999.; + + if (tt >= -1.0-UbMath::Epsilon<double>::val() && tt <= 1.0){ + if(xi >= -1.0+eta/wurzel3-UbMath::Epsilon<double>::val() && xi <= + 1.0-eta/wurzel3+UbMath::Epsilon<double>::val()){ + if (eta >= 0-UbMath::Epsilon<double>::val() && eta <= wurzel3+UbMath::Epsilon<double>::val()){ + /*xp = x1*(0.5-tt/2)+x2*(0.5+tt/2); + yp = y1*(0.5-tt/2)+y2*(0.5+tt/2); + zp = z1*(0.5-tt/2)+z2*(0.5+tt/2);*/ + return + static_cast<double>((sqrt(pow((x1*(0.5-tt/2)+x2*(0.5+tt/2))-x1,2) + +pow((y1*(0.5-tt/2)+y2*(0.5+tt/2))-y1,2)+pow((z1*(0.5-tt/2)+z2*(0.5+tt/2))-z1,2)))); + } + } + } + return (-999.); +} +/* +* Returns true if the specified 2D point lies within (or on the border of) this 2D triangle. +* @param point the 2D point to check +* @return true if the specified 2D point lies within (or on the border of) this 2D triangle +*/ + bool GbTriangle3D::enclosesPoint2D(double x1, double x2) + { + int i=0; + //Punkt(x1,x2) liegt auf einem der Eckpunkte + if(x1==this->getPoint(0)->getX1Coordinate() && x2 == this->getPoint(0)->getX2Coordinate()) return true; + if(x1==this->getPoint(1)->getX1Coordinate() && x2 == this->getPoint(1)->getX2Coordinate()) return true; + if(x1==this->getPoint(2)->getX1Coordinate() && x2 == this->getPoint(2)->getX2Coordinate()) return true; + + //Erste Grade aus dem zu pruefenden Punkt(x,y) und einem zweiten Punkt(x+0.333,y+2.333) + GbPoint3D p1; p1.setX1(x1); p1.setX2(x2); p1.setX3(0.0); + GbPoint3D p2; p2.setX1(x1+0.333); p2.setX2(x2+3.333); p2.setX3(0.0); + //Punkte des Dreiecks auf 2D reduziert + GbPoint3D dp1; dp1.setX1(this->getPoint(0)->getX1Coordinate()); dp1.setX2(this->getPoint(0)->getX2Coordinate()); dp1.setX3(0.0); + GbPoint3D dp2; dp2.setX1(this->getPoint(1)->getX1Coordinate()); dp2.setX2(this->getPoint(1)->getX2Coordinate()); dp2.setX3(0.0); + GbPoint3D dp3; dp3.setX1(this->getPoint(2)->getX1Coordinate()); dp3.setX2(this->getPoint(2)->getX2Coordinate()); dp3.setX3(0.0); + //ueberpruefen, ob der Punkt(x,y) innerhalt der Boundingbox des Dreiecks liegt + if( x1<this->getX1Maximum() && x1>getX1Minimum() + && x2<this->getX2Maximum() && x2>getX2Minimum()) + { + GbPoint3D* dummy = NULL; + //ueberpruefen, ob der Punkt innerhalb des Dreiecks liegt + dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp1,dp2); + if(dummy!=NULL) + { + if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate()) + { + delete dummy; + return true; + } + else if(dummy->getX1Coordinate()>p1.getX1Coordinate()) + { + i++; + } + else + { + i--; + } + } + if(dummy) delete dummy; + + dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp2,dp3); + if(dummy!=NULL) + { + if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate()) + { + if(dummy) delete dummy; + return true; + } + else if(dummy->getX1Coordinate()>p1.getX1Coordinate()) + { + i++; + } + else + { + i--; + } + } + if(dummy) delete dummy; + + dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp3,dp1); + if(dummy!=NULL) + { + if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate()) + { + if(dummy) delete dummy; + return true; + } + else if(dummy->getX1Coordinate()>p1.getX1Coordinate()) + { + i++; + } + else + { + i--; + } + } + if(dummy) delete dummy; + } + if(i==-1) return true; + if(i==1 ) return true; + + return false; + } + +///* +//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!). +//* @param rectangle the 2D rectangle +//* @return a new 2D polygon clipped by the specified 2D rectangle +//*/ +GbPolygon3D* GbTriangle3D::createClippedPolygon3D(GbCuboid3D* cube) +{ + return(GbSystem3D::clipPolygon3D(this->getPoints(), cube->getPoint1()->getX1Coordinate(), cube->getPoint1()->getX2Coordinate(), cube->getPoint1()->getX3Coordinate(), cube->getPoint2()->getX1Coordinate(), cube->getPoint2()->getX2Coordinate(), cube->getPoint2()->getX3Coordinate())); +} +///* +//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!). +//* @param p1 the 1st point of the rectangle +//* @param p2 the 2nd point of the rectangle +//* @return a new 2D polygon clipped by the specified 2D rectangle +//*/ +//public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2) +//{ +// return(GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2)); +//} +/* +* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!). +* @param p1x1 the 1st x1 coordinate of the rectangle +* @param p1x2 the 1st x2 coordinate of the rectangle +* @param p2x1 the 2nd x1 coordinate of the rectangle +* @param p2x2 the 2nd x2 coordinate of the rectangle +* @return a new 2D polygon clipped by the specified 2D rectangle +*/ +GbPolygon3D* GbTriangle3D::createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3) +{ + return(GbSystem3D::clipPolygon3D(this->getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2, p2x3)); +} + +/* +* Returns true if the specified 2D rectangle lies completely within this 2D triangle. +* @param rectangle the 2D rectangle to check +* @return true if the specified 2D rectangle lies completely within this 2D triangle +*/ +//bool enclosesRectangle2D(GbRectangle2D *rectangle) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2); +// return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea())); +//} +/* +* Returns true if the specified 2D rectangle lies completely within this 2D triangle. +* @param p1 the 1st point of the rectangle to check +* @param p2 the 2nd point of the rectangle to check triangle +* @return true if the specified 2D rectangle lies completely within this 2D +*/ +//public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2); +// return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2)))); +//} +/* +* Returns true if the specified 2D rectangle lies completely within this 2D triangle. +* @param p1x1 the 1st x1 coordinate of the rectangle to check +* @param p1x2 the 1st x2 coordinate of the rectangle to check +* @param p2x1 the 2nd x1 coordinate of the rectangle to check +* @param p2x2 the 2nd x2 coordinate of the rectangle to check +* @return true if the specified 2D rectangle lies completely within this 2D triangle +*/ +//public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2); +// return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2)))); +//} + +/* +* Returns true if the specified 2D rectangle is crossed by this 2D triangle. +* @param rectangle the 2D rectangle to check +* @return true if the specified 2D rectangle is crossed by this 2D triangle +*/ +//public boolean crossesRectangle2D(GbRectangle2D rectangle) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2); +// return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea())); +//} +/* +* Returns true if the specified 2D rectangle is crossed by this 2D triangle. +* @param p1 the 1st point of the rectangle to check +* @param p2 the 2nd point of the rectangle to check +* @return true if the specified 2D rectangle is crossed by this 2D triangle +*/ +//public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2); +// return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2)))); +//} +/* +* Returns true if the specified 2D rectangle is crossed by this 2D triangle. +* @param p1x1 the 1st x1 coordinate of the rectangle to check +* @param p1x2 the 1st x2 coordinate of the rectangle to check +* @param p2x1 the 2nd x1 coordinate of the rectangle to check +* @param p2x2 the 2nd x2 coordinate of the rectangle to check +* @return true if the specified 2D rectangle is crossed by this 2D triangle +*/ +//public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2); +// return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2)))); +//} + +/* +* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle. +* @param rectangle the 2D rectangle to check +* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle +*/ +//public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2); +// return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0)); +//} +/* +* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle. +* @param p1 the 1st point of the rectangle to check +* @param p2 the 2nd point of the rectangle to check +* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle +*/ +//public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2); +// return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0)); +//} +/* +* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle. +* @param p1x1 the 1st x1 coordinate of the rectangle to check +* @param p1x2 the 1st x2 coordinate of the rectangle to check +* @param p2x1 the 2nd x1 coordinate of the rectangle to check +* @param p2x2 the 2nd x2 coordinate of the rectangle to check +* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle +*/ +//public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2) +//{ +// GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2); +// return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0)); +//} +/*======================================================================*/ + + +/*======================================================================*/ +/* Private Methoden */ +/* */ +void GbTriangle3D::calculateValues() +{ + this->x1min = this->points[0]->x1; + this->x1max = this->points[0]->x1; + this->x2min = this->points[0]->x2; + this->x2max = this->points[0]->x2; + this->x3min = this->points[0]->x3; + this->x3max = this->points[0]->x3; + + if(this->points[1]->x1 < this->x1min) this->x1min = this->points[1]->x1; + if(this->points[1]->x1 > this->x1max) this->x1max = this->points[1]->x1; + if(this->points[1]->x2 < this->x2min) this->x2min = this->points[1]->x2; + if(this->points[1]->x2 > this->x2max) this->x2max = this->points[1]->x2; + if(this->points[1]->x3 < this->x3min) this->x3min = this->points[1]->x3; + if(this->points[1]->x3 > this->x3max) this->x3max = this->points[1]->x3; + + if(this->points[2]->x1 < this->x1min) this->x1min = this->points[2]->x1; + if(this->points[2]->x1 > this->x1max) this->x1max = this->points[2]->x1; + if(this->points[2]->x2 < this->x2min) this->x2min = this->points[2]->x2; + if(this->points[2]->x2 > this->x2max) this->x2max = this->points[2]->x2; + if(this->points[2]->x3 < this->x3min) this->x3min = this->points[2]->x3; + if(this->points[2]->x3 > this->x3max) this->x3max = this->points[2]->x3; + + this->x1s = (this->points[0]->x1+this->points[1]->x1+this->points[2]->x1)/3.0; + this->x2s = (this->points[0]->x2+this->points[1]->x2+this->points[2]->x2)/3.0; + this->x3s = (this->points[0]->x3+this->points[1]->x3+this->points[2]->x3)/3.0; + + GbVector3D A(points[0]->x1,points[0]->x2,points[0]->x3); + GbVector3D B(points[1]->x1,points[1]->x2,points[1]->x3); + GbVector3D C(points[2]->x1,points[2]->x2,points[2]->x3); + GbVector3D AB = B-A; + GbVector3D AC = C-A; + GbVector3D N = AB.Cross(AC); + this->area = 0.5*N.Length(); + this->consistent = true; +} +/*======================================================================*/ + + +/*======================================================================*/ +GbVector3D GbTriangle3D::getNormal() +{ + this->calculateNormal(); + return normal; +} +/*======================================================================*/ +void GbTriangle3D::init() +{ + x1s = 0.0; + x2s = 0.0; + x3s = 0.0; + x1min = 0.0; + x1max = 0.0; + x2min = 0.0; + x2max = 0.0; + area = 0.0; + consistent = false; + points.resize(3,NULL); +} +/*=======================================================*/ +void GbTriangle3D::calculateNormal() +{ + GbPoint3D*& a = points[0]; + GbPoint3D*& b = points[1]; + GbPoint3D*& c = points[2]; + normal[0] = ( c->getX3Coordinate() - a->getX3Coordinate()) * ( b->getX2Coordinate() - a->getX2Coordinate() ) - + ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() ); + normal[1] = ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() ) - + ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX3Coordinate() - a->getX3Coordinate() ); + normal[2] = ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() ) - + ( b->getX2Coordinate() - a->getX2Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() ); + normal.Normalize(); +} +/*=======================================================*/ +//toDo: +double GbTriangle3D::getDistanceFromPoint(GbVector3D punct) +{ + GbVector3D Point1(this->getPoint1()->getX1Coordinate(), this->getPoint1()->getX2Coordinate(), this->getPoint1()->getX3Coordinate()); + GbVector3D Point2(this->getPoint2()->getX1Coordinate(), this->getPoint2()->getX2Coordinate(), this->getPoint2()->getX3Coordinate()); + GbVector3D Point3(this->getPoint3()->getX1Coordinate(), this->getPoint3()->getX2Coordinate(), this->getPoint3()->getX3Coordinate()); + + GbVector3D kDiff = Point1 - punct; + GbVector3D kEdge0 = Point2 - Point1; + GbVector3D kEdge1 = Point3 - Point1; + double fA00 = kEdge0.SquaredLength(); + double fA01 = kEdge0.Dot(kEdge1); + double fA11 = kEdge1.SquaredLength(); + double fB0 = kDiff.Dot(kEdge0); + double fB1 = kDiff.Dot(kEdge1); + double fC = kDiff.SquaredLength(); + double fDet = fabs(fA00*fA11-fA01*fA01); + double fS = fA01*fB1-fA11*fB0; + double fT = fA01*fB0-fA00*fB1; + double fSqrDistance; + + if (fS + fT <= fDet) + { + if (fS < (double)0.0) + { + if (fT < (double)0.0) // region 4 + { + if (fB0 < (double)0.0) + { + fT = (double)0.0; + if (-fB0 >= fA00) + { + fS = (double)1.0; + fSqrDistance = fA00+((double)2.0)*fB0+fC; + } + else + { + fS = -fB0/fA00; + fSqrDistance = fB0*fS+fC; + } + } + else + { + fS = (double)0.0; + if (fB1 >= (double)0.0) + { + fT = (double)0.0; + fSqrDistance = fC; + } + else if (-fB1 >= fA11) + { + fT = (double)1.0; + fSqrDistance = fA11+((double)2.0)*fB1+fC; + } + else + { + fT = -fB1/fA11; + fSqrDistance = fB1*fT+fC; + } + } + } + else // region 3 + { + fS = (double)0.0; + if (fB1 >= (double)0.0) + { + fT = (double)0.0; + fSqrDistance = fC; + } + else if (-fB1 >= fA11) + { + fT = (double)1.0; + fSqrDistance = fA11+((double)2.0)*fB1+fC; + } + else + { + fT = -fB1/fA11; + fSqrDistance = fB1*fT+fC; + } + } + } + else if (fT < (double)0.0) // region 5 + { + fT = (double)0.0; + if (fB0 >= (double)0.0) + { + fS = (double)0.0; + fSqrDistance = fC; + } + else if (-fB0 >= fA00) + { + fS = (double)1.0; + fSqrDistance = fA00+((double)2.0)*fB0+fC; + } + else + { + fS = -fB0/fA00; + fSqrDistance = fB0*fS+fC; + } + } + else // region 0 + { + // minimum at interior point + double fInvDet = ((double)1.0)/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) + + fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC; + } + } + else + { + double fTmp0, fTmp1, fNumer, fDenom; + + if (fS < (double)0.0) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if (fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if (fNumer >= fDenom) + { + fS = (double)1.0; + fT = (double)0.0; + fSqrDistance = fA00+((double)2.0)*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = (double)1.0 - fS; + fSqrDistance = fS*(fA00*fS+fA01*fT+2.0f*fB0) + + fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC; + } + } + else + { + fS = (double)0.0; + if (fTmp1 <= (double)0.0) + { + fT = (double)1.0; + fSqrDistance = fA11+((double)2.0)*fB1+fC; + } + else if (fB1 >= (double)0.0) + { + fT = (double)0.0; + fSqrDistance = fC; + } + else + { + fT = -fB1/fA11; + fSqrDistance = fB1*fT+fC; + } + } + } + else if (fT < (double)0.0) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if (fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-((double)2.0)*fA01+fA11; + if (fNumer >= fDenom) + { + fT = (double)1.0; + fS = (double)0.0; + fSqrDistance = fA11+((double)2.0)*fB1+fC; + } + else + { + fT = fNumer/fDenom; + fS = (double)1.0 - fT; + fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) + + fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC; + } + } + else + { + fT = (double)0.0; + if (fTmp1 <= (double)0.0) + { + fS = (double)1.0; + fSqrDistance = fA00+((double)2.0)*fB0+fC; + } + else if (fB0 >= (double)0.0) + { + fS = (double)0.0; + fSqrDistance = fC; + } + else + { + fS = -fB0/fA00; + fSqrDistance = fB0*fS+fC; + } + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if (fNumer <= (double)0.0) + { + fS = (double)0.0; + fT = (double)1.0; + fSqrDistance = fA11+((double)2.0)*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if (fNumer >= fDenom) + { + fS = (double)1.0; + fT = (double)0.0; + fSqrDistance = fA00+((double)2.0)*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = (double)1.0 - fS; + fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) + + fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC; + } + } + } + } + + // account for numerical round-off error + if (fSqrDistance < (double)0.0) + { + fSqrDistance = (double)0.0; + } +/* + m_kClosestPoint0 = punct; + m_kClosestPoint1 = m_rkTriangle.V[0] + fS*kEdge0 + fT*kEdge1; + m_afTriangleBary[1] = fS; + m_afTriangleBary[2] = fT; + m_afTriangleBary[0] = (double)1.0 - fS - fT; +*/ + return sqrt(fSqrDistance); +} diff --git a/VirtualFluidsBasics/geometry3d/GbTriangle3D.h b/VirtualFluidsBasics/geometry3d/GbTriangle3D.h new file mode 100644 index 0000000000000000000000000000000000000000..61a8f5ff5b83df090cc5c1c0f1b98fa0ad04aac0 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbTriangle3D.h @@ -0,0 +1,216 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbTriangle3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBTRIANGLE3D_H +#define GBTRIANGLE3D_H + +#include <sstream> + +#include <GbObject3D.h> +#include <GbVector3D.h> +#include <GbPoint3D.h> + +#include <PointerDefinitions.h> + +class GbCuboid3D; +class GbPolygon3D; +class GbObject3DCreator; + +////////////////////////////////////////////////////////////////////////// +//! +//! \class GbTriangle3D +//! +//! \brief This Class provides basic 3D triangle objects. +//! \details The describing points are observed by 2D triangle objects. +//! +////////////////////////////////////////////////////////////////////////// + +class GbTriangle3D : public GbObject3D , public UbObserver +{ +public: + /*======================================================================*/ + /* Konstruktoren */ + /* */ + GbTriangle3D(); + GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3); + GbTriangle3D(GbTriangle3D* triangle); + ~GbTriangle3D(); + /*======================================================================*/ + /* Methoden */ + /* */ + GbTriangle3D* clone(); + void finalize() + { + this->deletePoints(); + } + + GbPoint3D* getPoint1() { return this->points[0]; } + GbPoint3D* getPoint2() { return this->points[1]; } + GbPoint3D* getPoint3() { return this->points[2]; } + + GbVector3D getNormal(); + void calculateNormal(); + + void deletePoints(); + + int contains(GbPoint3D* point); + int containsEqual(GbPoint3D* point); + GbPoint3D* getPoint(const int& index); + std::vector<GbPoint3D> getPoints(); + double getArea(); + double getX1Centroid(); + double getX1Minimum(); + double getX1Maximum(); + double getX2Centroid(); + double getX2Minimum(); + double getX2Maximum(); + double getX3Centroid(); + double getX3Minimum(); + double getX3Maximum(); + + void setInconsistent() { this->consistent = false;} + + void setPoint(GbPoint3D *point, int index); + + //bool equals(GbObject3D *object) + std::vector<GbTriangle3D*> getSurfaceTriangleSet(); + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3) + { + //der einfachheit halber ... + return false; + //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented"); + } + bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary) + { + //der einfachheit halber ... + pointIsOnBoundary = false; + return false; + //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented"); + } + bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; } + + + // get distance from a point to the triangle + //todo CHANGE... + double getDistanceFromPoint(GbVector3D punct); + + std::string toString(); + + /*======================================================================*/ + /* Calculation */ + /* */ +// std::vector<GbPoint3D> calculateIntersectionPoints3D(GbLine3D *line); + bool hasRaytracing() { return true; } + /*|r| must be 1! einheitsvector!!*/ + double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3); +// bool isPointOnEdge(GbVector3D& q); + + GbPoint3D* calculateIntersectionPoints3D(GbLine3D* line); + GbPoint3D* calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2); + double calculateDistanceToPoint3D(GbPoint3D *point); + double calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3); + double calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, const double& x2, const double& y2, const double& z2); + + bool enclosesPoint2D(double x1, double x2); + GbPolygon3D* createClippedPolygon3D(GbCuboid3D* cube); + GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2); + //public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2); + GbPolygon3D* createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3); + //bool enclosesRectangle2D(GbRectangle2D *rectangle); + //public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2); + //public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2); + //public boolean crossesRectangle2D(GbRectangle2D rectangle); + //public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2); + //public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2); + //public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle); + //public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2); + //public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2); + /*======================================================================*/ + /*======================================================================*/ + /* Private Methoden */ + /* */ + virtual void calculateValues(); + + + //virtuelle Methoden von UbObserver + //!! quick and dirty von sirann !! + void objectChanged(UbObservable* changedObject) + { + GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject); + if(!point || ( this->points[0]!=point && this->points[1]!=point && this->points[2]!=point) ) + return; + + this->consistent = false; + } + void objectWillBeDeleted(UbObservable* objectForDeletion) + { + if(this->points[0]) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[0]); + if(objectForDeletion == observedObj) { this->points[0] = NULL; } + } + if(this->points[1]) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[1]); + if(objectForDeletion == observedObj) { this->points[1] = NULL; } + } + if(this->points[2]) + { + UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[2]); + if(objectForDeletion == observedObj) { this->points[2] = NULL; } + } + //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo + } + using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere + +protected: + bool consistent; + double x1s; + double x2s; + double x3s; + double x1min; + double x1max; + double x2min; + double x2max; + double x3min; + double x3max; + double area; + + GbVector3D normal; + std::vector<GbPoint3D*> points; + +private: + void init(); +}; +/*=========================================================================*/ + +#endif diff --git a/VirtualFluidsBasics/geometry3d/GbVector3D.cpp b/VirtualFluidsBasics/geometry3d/GbVector3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6246a7d15316bb432894937c43523f5a99ba5431 --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbVector3D.cpp @@ -0,0 +1,675 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbVector3D.cpp +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#include <GbVector3D.h> +#include <GbPoint3D.h> + +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbInfinity.h> + +using namespace std; + + +const GbVector3D GbVector3D::ZERO(0.0,0.0,0.0); +const GbVector3D GbVector3D::UNIT_X1(1.0,0.0,0.0); +const GbVector3D GbVector3D::UNIT_X2(0.0,1.0,0.0); +const GbVector3D GbVector3D::UNIT_X3(0.0,0.0,1.0); + +//---------------------------------------------------------------------------- +GbVector3D::GbVector3D () +{ + m_afTuple[0] = 0.0; + m_afTuple[1] = 0.0; + m_afTuple[2] = 0.0; +} +//---------------------------------------------------------------------------- +GbVector3D::GbVector3D (const double& fX, const double& fY, const double& fZ) +{ + m_afTuple[0] = fX; + m_afTuple[1] = fY; + m_afTuple[2] = fZ; +} +//---------------------------------------------------------------------------- +GbVector3D::GbVector3D (const GbVector3D& rkV) +{ + m_afTuple[0] = rkV.m_afTuple[0]; + m_afTuple[1] = rkV.m_afTuple[1]; + m_afTuple[2] = rkV.m_afTuple[2]; +} +//---------------------------------------------------------------------------- + +GbVector3D::GbVector3D (const GbPoint3D& point) +{ + m_afTuple[0] = point.x1; + m_afTuple[1] = point.x2; + m_afTuple[2] = point.x3; +} + +//---------------------------------------------------------------------------- +string GbVector3D::toString() +{ + std::stringstream ss; + ss<< "GbVector3D["<<m_afTuple[0]<<","<<m_afTuple[1]<<","<<m_afTuple[2]<<"]"; + ss<<endl; + return((ss.str()).c_str()); +} +//---------------------------------------------------------------------------- +GbVector3D::operator const double* () const +{ + return m_afTuple; +} +//---------------------------------------------------------------------------- +GbVector3D::operator double* () +{ + return m_afTuple; +} +//---------------------------------------------------------------------------- +double GbVector3D::operator[] (int i) const +{ + assert( 0 <= i && i <= 2 ); + if ( i < 0 ) + i = 0; + else if ( i > 2 ) + i = 2; + + return m_afTuple[i]; +} +//---------------------------------------------------------------------------- +double& GbVector3D::operator[] (int i) +{ + assert( 0 <= i && i <= 2 ); + if ( i < 0 ) + i = 0; + else if ( i > 2 ) + i = 2; + + return m_afTuple[i]; +} +//---------------------------------------------------------------------------- +double GbVector3D::X1 () const +{ + return m_afTuple[0]; +} +//---------------------------------------------------------------------------- +double& GbVector3D::X1 () +{ + return m_afTuple[0]; +} +//---------------------------------------------------------------------------- +double GbVector3D::X2 () const +{ + return m_afTuple[1]; +} +//---------------------------------------------------------------------------- +double& GbVector3D::X2 () +{ + return m_afTuple[1]; +} +//---------------------------------------------------------------------------- +double GbVector3D::X3 () const +{ + return m_afTuple[2]; +} +//---------------------------------------------------------------------------- +double& GbVector3D::X3 () +{ + return m_afTuple[2]; +} +//---------------------------------------------------------------------------- +GbVector3D& GbVector3D::operator= (const GbVector3D& rkV) +{ + m_afTuple[0] = rkV.m_afTuple[0]; + m_afTuple[1] = rkV.m_afTuple[1]; + m_afTuple[2] = rkV.m_afTuple[2]; + return *this; +} +//---------------------------------------------------------------------------- +int GbVector3D::CompareArrays (const GbVector3D& rkV) const +{ + return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(double)); +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator== (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) == 0; +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator!= (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) != 0; +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator< (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) < 0; +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator<= (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) <= 0; +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator> (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) > 0; +} +//---------------------------------------------------------------------------- +bool GbVector3D::operator>= (const GbVector3D& rkV) const +{ + return CompareArrays(rkV) >= 0; +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::operator+ (const GbVector3D& rkV) const +{ + return GbVector3D( + m_afTuple[0]+rkV.m_afTuple[0], + m_afTuple[1]+rkV.m_afTuple[1], + m_afTuple[2]+rkV.m_afTuple[2]); +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::Add(GbVector3D& vector) +{ + return GbVector3D( + m_afTuple[0]+vector.m_afTuple[0], + m_afTuple[1]+vector.m_afTuple[1], + m_afTuple[2]+vector.m_afTuple[2]); +} + +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::operator- (const GbVector3D& rkV) const +{ + return GbVector3D( + m_afTuple[0]-rkV.m_afTuple[0], + m_afTuple[1]-rkV.m_afTuple[1], + m_afTuple[2]-rkV.m_afTuple[2]); +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::Subtract(GbVector3D& vector) +{ + return GbVector3D( + m_afTuple[0]-vector.m_afTuple[0], + m_afTuple[1]-vector.m_afTuple[1], + m_afTuple[2]-vector.m_afTuple[2]); +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::operator* (const double& fScalar) const +{ + return GbVector3D( fScalar*m_afTuple[0], + fScalar*m_afTuple[1], + fScalar*m_afTuple[2]); +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::operator/ (const double& fScalar) const +{ + GbVector3D kQuot; + + if ( fScalar != 0.0 ) + { + double fInvScalar = 1.0/fScalar; + kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0]; + kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1]; + kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2]; + } + else + { + kQuot.m_afTuple[0] = Ub::inf; + kQuot.m_afTuple[1] = Ub::inf; + kQuot.m_afTuple[2] = Ub::inf; + } + + return kQuot; +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::operator- () const +{ + return GbVector3D( + -m_afTuple[0], + -m_afTuple[1], + -m_afTuple[2]); +} +//---------------------------------------------------------------------------- +GbVector3D operator* (const double& fScalar, const GbVector3D& rkV) +{ + return GbVector3D( + fScalar*rkV[0], + fScalar*rkV[1], + fScalar*rkV[2]); +} +//---------------------------------------------------------------------------- +GbVector3D& GbVector3D::operator+= (const GbVector3D& rkV) +{ + m_afTuple[0] += rkV.m_afTuple[0]; + m_afTuple[1] += rkV.m_afTuple[1]; + m_afTuple[2] += rkV.m_afTuple[2]; + return *this; +} +//---------------------------------------------------------------------------- +GbVector3D& GbVector3D::operator-= (const GbVector3D& rkV) +{ + m_afTuple[0] -= rkV.m_afTuple[0]; + m_afTuple[1] -= rkV.m_afTuple[1]; + m_afTuple[2] -= rkV.m_afTuple[2]; + return *this; +} +//---------------------------------------------------------------------------- +GbVector3D& GbVector3D::operator*= (const double& fScalar) +{ + m_afTuple[0] *= fScalar; + m_afTuple[1] *= fScalar; + m_afTuple[2] *= fScalar; + return *this; +} +//---------------------------------------------------------------------------- +GbVector3D& GbVector3D::operator/= (const double& fScalar) +{ + if ( fScalar != (double)0.0 ) + { + double fInvScalar = ((double)1.0)/fScalar; + m_afTuple[0] *= fInvScalar; + m_afTuple[1] *= fInvScalar; + m_afTuple[2] *= fInvScalar; + } + else + { + m_afTuple[0] = Ub::inf; + m_afTuple[1] = Ub::inf; + m_afTuple[2] = Ub::inf; + } + + return *this; +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::Scale(const double& x) +{ + GbVector3D PointA(0.0,0.0,0.0); + PointA.m_afTuple[0] = x * m_afTuple[0]; + PointA.m_afTuple[1] = x * m_afTuple[1]; + PointA.m_afTuple[2] = x * m_afTuple[2]; + return PointA; +} + +//---------------------------------------------------------------------------- +double GbVector3D::Length () const +{ + return std::sqrt( + m_afTuple[0]*m_afTuple[0] + + m_afTuple[1]*m_afTuple[1] + + m_afTuple[2]*m_afTuple[2]); +} +//---------------------------------------------------------------------------- +double GbVector3D::SquaredLength () const +{ + return + m_afTuple[0]*m_afTuple[0] + + m_afTuple[1]*m_afTuple[1] + + m_afTuple[2]*m_afTuple[2]; +} +//---------------------------------------------------------------------------- +double GbVector3D::Dot (const GbVector3D& rkV) const +{ + return + m_afTuple[0]*rkV.m_afTuple[0] + + m_afTuple[1]*rkV.m_afTuple[1] + + m_afTuple[2]*rkV.m_afTuple[2]; +} +//---------------------------------------------------------------------------- +double GbVector3D::Normalize () +{ + double fLength = Length(); + + if ( fLength > UbMath::Epsilon<double>::val() ) + { + double fInvLength = ((double)1.0)/fLength; + m_afTuple[0] *= fInvLength; + m_afTuple[1] *= fInvLength; + m_afTuple[2] *= fInvLength; + } + else + { + fLength = 0.0; + m_afTuple[0] = 0.0; + m_afTuple[1] = 0.0; + m_afTuple[2] = 0.0; + } + + return fLength; +} +//---------------------------------------------------------------------------- +GbVector3D GbVector3D::Cross (const GbVector3D& rkV) const +{ + return GbVector3D( + m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1], + m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2], + m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]); +} + +//---------------------------------------------------------------------------- + +GbVector3D GbVector3D::UnitCross (const GbVector3D& rkV) const +{ + GbVector3D kCross( + m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1], + m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2], + m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]); + kCross.Normalize(); + return kCross; +} +//---------------------------------------------------------------------------- +void GbVector3D::GetBarycentrics (const GbVector3D& rkV0, + const GbVector3D& rkV1, const GbVector3D& rkV2, + const GbVector3D& rkV3, double afBary[4]) const +{ + // compute the vectors relative to V3 of the tetrahedron + GbVector3D akDiff[4] = + { + rkV0 - rkV3, + rkV1 - rkV3, + rkV2 - rkV3, + *this - rkV3 + }; + + // If the vertices have large magnitude, the linear system of + // equations for computing barycentric coordinates can be + // ill-conditioned. To avoid this, uniformly scale the tetrahedron + // edges to be of order 1. The scaling of all differences does not + // change the barycentric coordinates. + double fMax = (double)0.0; + int i; + for (i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + double fValue = std::fabs(akDiff[i][j]); + if ( fValue > fMax ) + fMax = fValue; + } + } + + // scale down only large data + if ( fMax > (double)1.0 ) + { + double fInvMax = ((double)1.0)/fMax; + for (i = 0; i < 4; i++) + akDiff[i] *= fInvMax; + } + + double fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2])); + GbVector3D kE1cE2 = akDiff[1].Cross(akDiff[2]); + GbVector3D kE2cE0 = akDiff[2].Cross(akDiff[0]); + GbVector3D kE0cE1 = akDiff[0].Cross(akDiff[1]); + if ( std::fabs(fDet) > UbMath::Epsilon<double>::val() ) + { + double fInvDet = ((double)1.0)/fDet; + afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet; + afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet; + afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet; + afBary[3] = (double)1.0 - afBary[0] - afBary[1] - afBary[2]; + } + else + { + // The tetrahedron is potentially flat. Determine the face of + // maximum area and compute barycentric coordinates with respect + // to that face. + GbVector3D kE02 = rkV0 - rkV2; + GbVector3D kE12 = rkV1 - rkV2; + GbVector3D kE02cE12 = kE02.Cross(kE12); + double fMaxSqrArea = kE02cE12.SquaredLength(); + int iMaxIndex = 3; + double fSqrArea = kE0cE1.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 0; + fMaxSqrArea = fSqrArea; + } + fSqrArea = kE1cE2.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 1; + fMaxSqrArea = fSqrArea; + } + fSqrArea = kE2cE0.SquaredLength(); + if ( fSqrArea > fMaxSqrArea ) + { + iMaxIndex = 2; + fMaxSqrArea = fSqrArea; + } + + if ( fMaxSqrArea > UbMath::Epsilon<double>::val() ) + { + double fInvSqrArea = ((double)1.0)/fMaxSqrArea; + GbVector3D kTmp; + if ( iMaxIndex == 0 ) + { + kTmp = akDiff[3].Cross(akDiff[1]); + afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea; + kTmp = akDiff[0].Cross(akDiff[3]); + afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea; + afBary[2] = (double)0.0; + afBary[3] = (double)1.0 - afBary[0] - afBary[1]; + } + else if ( iMaxIndex == 1 ) + { + afBary[0] = (double)0.0; + kTmp = akDiff[3].Cross(akDiff[2]); + afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea; + kTmp = akDiff[1].Cross(akDiff[3]); + afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea; + afBary[3] = (double)1.0 - afBary[1] - afBary[2]; + } + else if ( iMaxIndex == 2 ) + { + kTmp = akDiff[2].Cross(akDiff[3]); + afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea; + afBary[1] = (double)0.0; + kTmp = akDiff[3].Cross(akDiff[0]); + afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea; + afBary[3] = (double)1.0 - afBary[0] - afBary[2]; + } + else + { + akDiff[3] = *this - rkV2; + kTmp = akDiff[3].Cross(kE12); + afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea; + kTmp = kE02.Cross(akDiff[3]); + afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea; + afBary[2] = (double)1.0 - afBary[0] - afBary[1]; + afBary[3] = (double)0.0; + } + } + else + { + // The tetrahedron is potentially a sliver. Determine the edge of + // maximum length and compute barycentric coordinates with respect + // to that edge. + double fMaxSqrLength = akDiff[0].SquaredLength(); + iMaxIndex = 0; // <V0,V3> + double fSqrLength = akDiff[1].SquaredLength(); + if ( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 1; // <V1,V3> + fMaxSqrLength = fSqrLength; + } + fSqrLength = akDiff[2].SquaredLength(); + if ( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 2; // <V2,V3> + fMaxSqrLength = fSqrLength; + } + fSqrLength = kE02.SquaredLength(); + if ( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 3; // <V0,V2> + fMaxSqrLength = fSqrLength; + } + fSqrLength = kE12.SquaredLength(); + if ( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 4; // <V1,V2> + fMaxSqrLength = fSqrLength; + } + GbVector3D kE01 = rkV0 - rkV1; + fSqrLength = kE01.SquaredLength(); + if ( fSqrLength > fMaxSqrLength ) + { + iMaxIndex = 5; // <V0,V1> + fMaxSqrLength = fSqrLength; + } + + if ( fMaxSqrLength > UbMath::Epsilon<double>::val() ) + { + double fInvSqrLength = ((double)1.0)/fMaxSqrLength; + if ( iMaxIndex == 0 ) + { + // P-V3 = t*(V0-V3) + afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength; + afBary[1] = (double)0.0; + afBary[2] = (double)0.0; + afBary[3] = (double)1.0 - afBary[0]; + } + else if ( iMaxIndex == 1 ) + { + // P-V3 = t*(V1-V3) + afBary[0] = (double)0.0; + afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength; + afBary[2] = (double)0.0; + afBary[3] = (double)1.0 - afBary[1]; + } + else if ( iMaxIndex == 2 ) + { + // P-V3 = t*(V2-V3) + afBary[0] = (double)0.0; + afBary[1] = (double)0.0; + afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength; + afBary[3] = (double)1.0 - afBary[2]; + } + else if ( iMaxIndex == 3 ) + { + // P-V2 = t*(V0-V2) + akDiff[3] = *this - rkV2; + afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength; + afBary[1] = (double)0.0; + afBary[2] = (double)1.0 - afBary[0]; + afBary[3] = (double)0.0; + } + else if ( iMaxIndex == 4 ) + { + // P-V2 = t*(V1-V2) + akDiff[3] = *this - rkV2; + afBary[0] = (double)0.0; + afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength; + afBary[2] = (double)1.0 - afBary[1]; + afBary[3] = (double)0.0; + } + else + { + // P-V1 = t*(V0-V1) + akDiff[3] = *this - rkV1; + afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength; + afBary[1] = (double)1.0 - afBary[0]; + afBary[2] = (double)0.0; + afBary[3] = (double)0.0; + } + } + else + { + // tetrahedron is a nearly a point, just return equal weights + afBary[0] = (double)0.25; + afBary[1] = afBary[0]; + afBary[2] = afBary[0]; + afBary[3] = afBary[0]; + } + } + } +} +//---------------------------------------------------------------------------- +void GbVector3D::Orthonormalize (GbVector3D& rkU, GbVector3D& rkV, GbVector3D& rkW) +{ + // If the input vectors are v0, v1, and v2, then the Gram-Schmidt + // orthonormalization produces vectors u0, u1, and u2 as follows, + // + // u0 = v0/|v0| + // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| + // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| + // + // where |A| indicates length of vector A and A*B indicates dot + // product of vectors A and B. + + // compute u0 + rkU.Normalize(); + + // compute u1 + double fDot0 = rkU.Dot(rkV); + rkV -= fDot0*rkU; + rkV.Normalize(); + + // compute u2 + double fDot1 = rkV.Dot(rkW); + fDot0 = rkU.Dot(rkW); + rkW -= fDot0*rkU + fDot1*rkV; + rkW.Normalize(); +} +//---------------------------------------------------------------------------- +void GbVector3D::Orthonormalize (GbVector3D* akV) +{ + Orthonormalize(akV[0],akV[1],akV[2]); +} +//---------------------------------------------------------------------------- +void GbVector3D::GenerateOrthonormalBasis (GbVector3D& rkU, GbVector3D& rkV, + GbVector3D& rkW, bool bUnitLengthW) +{ + if ( !bUnitLengthW ) + rkW.Normalize(); + + double fInvLength; + + if ( std::fabs(rkW.m_afTuple[0]) >= + std::fabs(rkW.m_afTuple[1]) ) + { + // W.x or W.z is the largest magnitude component, swap them + fInvLength = UbMath::invSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] + rkW.m_afTuple[2]*rkW.m_afTuple[2]); + rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength; + rkU.m_afTuple[1] = (double)0.0; + rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength; + } + else + { + // W.y or W.z is the largest magnitude component, swap them + fInvLength = UbMath::invSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] + rkW.m_afTuple[2]*rkW.m_afTuple[2]); + rkU.m_afTuple[0] = (double)0.0; + rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength; + rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength; + } + + rkV = rkW.Cross(rkU); +} +//---------------------------------------------------------------------------- + diff --git a/VirtualFluidsBasics/geometry3d/GbVector3D.h b/VirtualFluidsBasics/geometry3d/GbVector3D.h new file mode 100644 index 0000000000000000000000000000000000000000..61184e8e0ff1e7ba621b095bb7de4f1f3c2b098e --- /dev/null +++ b/VirtualFluidsBasics/geometry3d/GbVector3D.h @@ -0,0 +1,144 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GbVector3D.h +//! \ingroup geometry3d +//! \author Soeren Freudiger, Sebastian Geller +//======================================================================================= +#ifndef GBVECTOR3D_H +#define GBVECTOR3D_H + +#include <cfloat> +#include <cassert> +#include <string> + +#include <PointerDefinitions.h> + +class GbPoint3D; + +//! \brief This Class provides basic 3D vector objects. +class GbVector3D +{ +public: + // construction + GbVector3D (); + GbVector3D (const double& fX1, const double& fX2, const double& fX3); + GbVector3D (const GbVector3D& rkV); + GbVector3D (const GbPoint3D& rkV); + + std::string toString(); + + // coordinate access + operator const double* () const; + operator double* (); + double operator[] (int i) const; + double& operator[] (int i); + double X1 () const; + double& X1 (); + double X2 () const; + double& X2 (); + double X3 () const; + double& X3 (); + + // assignment + GbVector3D& operator= (const GbVector3D& rkV); + + // comparison + bool operator== (const GbVector3D& rkV) const; + bool operator!= (const GbVector3D& rkV) const; + bool operator< (const GbVector3D& rkV) const; + bool operator<= (const GbVector3D& rkV) const; + bool operator> (const GbVector3D& rkV) const; + bool operator>= (const GbVector3D& rkV) const; + + // arithmetic operations + GbVector3D operator+ (const GbVector3D& rkV) const; + GbVector3D operator- (const GbVector3D& rkV) const; + GbVector3D operator* (const double& fScalar) const; + GbVector3D operator/ (const double& fScalar) const; + GbVector3D operator- () const; + + // arithmetic updates + GbVector3D& operator+= (const GbVector3D& rkV); + GbVector3D& operator-= (const GbVector3D& rkV); + GbVector3D& operator*= (const double& fScalar); + GbVector3D& operator/= (const double& fScalar); + + GbVector3D Add(GbVector3D& vector); + GbVector3D Subtract(GbVector3D& vector); + GbVector3D Scale(const double& x); + + // vector operations + double Length () const; + double SquaredLength () const; + double Dot (const GbVector3D& rkV) const; + double Normalize (); + + // The cross products are computed using the right-handed rule. Be aware + // that some graphics APIs use a left-handed rule. If you have to compute + // a cross product with these functions and send the result to the API + // that expects left-handed, you will need to change sign on the vector + // (replace each component value c by -c). + GbVector3D Cross (const GbVector3D& rkV) const; + GbVector3D UnitCross (const GbVector3D& rkV) const; + + // Compute the barycentric coordinates of the point with respect to the + // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where + // b0 + b1 + b2 + b3 = 1. + void GetBarycentrics (const GbVector3D& rkV0, + const GbVector3D& rkV1, const GbVector3D& rkV2, + const GbVector3D& rkV3, double afBary[4]) const; + + // Gram-Schmidt orthonormalization. Take linearly independent vectors + // U, V, and W and compute an orthonormal set (unit length, mutually + // perpendicular). + static void Orthonormalize (GbVector3D& rkU, GbVector3D& rkV, GbVector3D& rkW); + static void Orthonormalize (GbVector3D* akV); + + // Input W must be initialized to a nonzero vector, output is {U,V,W}, + // an orthonormal basis. A hint is provided about whether or not W + // is already unit length. + static void GenerateOrthonormalBasis (GbVector3D& rkU, GbVector3D& rkV, + GbVector3D& rkW, bool bUnitLengthW); + + // special vectors + static const GbVector3D ZERO; + static const GbVector3D UNIT_X1; + static const GbVector3D UNIT_X2; + static const GbVector3D UNIT_X3; + +private: + // support for comparisons + int CompareArrays (const GbVector3D& rkV) const; + + double m_afTuple[3]; +}; + +GbVector3D operator* (const double& fScalar, const GbVector3D& rkV); + +#endif //GBVECTOR3D_H diff --git a/VirtualFluidsCore/BoundaryConditions/BCAdapter.h b/VirtualFluidsCore/BoundaryConditions/BCAdapter.h new file mode 100644 index 0000000000000000000000000000000000000000..26437dafc6c6075d5ba8d8f64aecabd6c207e089 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCAdapter.h @@ -0,0 +1,92 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCAdapter.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= +#ifndef BCAdapter_H +#define BCAdapter_H + +#include <PointerDefinitions.h> + +#include "BoundaryConditions.h" +#include "BCAlgorithm.h" + +class D3Q27Interactor; + +//! \brief Abstract class of baundary conditions adapter +//! \details BCAdapter supports the definition of boundary conditions in grid generation +class BCAdapter +{ +public: + BCAdapter() + : secondaryBcOption(0) + , type(0) + , algorithmType(-1) + { + } + //! \param secondaryBcOption additional option of boundary conditions + BCAdapter(const short& secondaryBcOption) + : secondaryBcOption(secondaryBcOption) + , type(0) + , algorithmType(-1) + { + } + virtual ~BCAdapter() {} + + //methods + bool isTimeDependent() { return((this->type & TIMEDEPENDENT) == TIMEDEPENDENT); } + + virtual short getSecondaryBcOption() { return this->secondaryBcOption; } + virtual void setSecondaryBcOption(const short& val) { this->secondaryBcOption=val; } + + virtual void init(const D3Q27Interactor* const& interactor, const double& time=0) = 0; + virtual void update(const D3Q27Interactor* const& interactor, const double& time=0) = 0; + + virtual void adaptBC( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 ) = 0; + virtual void adaptBCForDirection( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 ) = 0; + + void setBcAlgorithm(SPtr<BCAlgorithm> alg) {algorithmType = alg->getType(); algorithm = alg;} + SPtr<BCAlgorithm> getAlgorithm() {return algorithm;} + char getBcAlgorithmType() {return algorithmType;} + +protected: + short secondaryBcOption; + + char type; + + SPtr<BCAlgorithm> algorithm; + char algorithmType; + + static const char TIMEDEPENDENT = 1<<0;//'1'; + static const char TIMEPERIODIC = 1<<1;//'2'; +}; + + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.cpp b/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..630b3ec7e4922309da0630eb09f0aa60c0e2cfa2 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.cpp @@ -0,0 +1,103 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCAlgorithm.cpp +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#include "BCAlgorithm.h" + +#include "BoundaryConditions.h" +#include "EsoTwist3D.h" +#include "BCArray3D.h" + + +BCAlgorithm::BCAlgorithm() : compressible(false) +{ + +} +////////////////////////////////////////////////////////////////////////// +void BCAlgorithm::setNodeIndex(int x1, int x2, int x3) +{ + this->x1 = x1; + this->x2 = x2; + this->x3 = x3; +} +////////////////////////////////////////////////////////////////////////// +void BCAlgorithm::setBcPointer(SPtr<BoundaryConditions> bcPtr) +{ + this->bcPtr = bcPtr; +} +////////////////////////////////////////////////////////////////////////// +void BCAlgorithm::setCompressible(bool c) +{ + compressible = c; + + if (this->compressible) + { + calcFeqsForDirFct = &D3Q27System::getCompFeqForDirection; + calcMacrosFct = &D3Q27System::calcCompMacroscopicValues; + calcFeqFct = &D3Q27System::calcCompFeq; + compressibleFactor = 1.0; + } + else + { + calcFeqsForDirFct = &D3Q27System::getIncompFeqForDirection; + calcMacrosFct = &D3Q27System::calcIncompMacroscopicValues; + calcFeqFct = &D3Q27System::calcIncompFeq; + compressibleFactor = 0.0; + } +} +////////////////////////////////////////////////////////////////////////// +void BCAlgorithm::setCollFactor(LBMReal cf) +{ + collFactor = cf; +} + +////////////////////////////////////////////////////////////////////////// +char BCAlgorithm::getType() +{ + return type; +} +////////////////////////////////////////////////////////////////////////// +bool BCAlgorithm::isPreCollision() +{ + return preCollision; +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCArray3D> BCAlgorithm::getBcArray() +{ + return bcArray; +} +////////////////////////////////////////////////////////////////////////// +void BCAlgorithm::setBcArray(SPtr<BCArray3D> bcarray) +{ + bcArray = bcarray; +} + diff --git a/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.h b/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..5a3944c7e2c9ead7687818553446ef4cf1d2d5d8 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCAlgorithm.h @@ -0,0 +1,100 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCAlgorithm.h +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BOUNDARYCONDITIONS_H +#define BOUNDARYCONDITIONS_H + +#include <PointerDefinitions.h> + +#include "D3Q27System.h" + +class DistributionArray3D; +class BCArray3D; +class BoundaryConditions; + +//! \brief Abstract class of baundary conditions algorithm +//! \details BCAlgorithm provides interface for implementation of diferent boundary conditions +class BCAlgorithm +{ +public: + static const char VelocityBCAlgorithm = 0; + static const char EqDensityBCAlgorithm = 1; + static const char NonEqDensityBCAlgorithm = 2; + static const char NoSlipBCAlgorithm = 3; + static const char SlipBCAlgorithm = 4; + static const char HighViscosityNoSlipBCAlgorithm = 5; + static const char ThinWallNoSlipBCAlgorithm = 6; + static const char VelocityWithDensityBCAlgorithm = 7; + static const char NonReflectingOutflowBCAlgorithm = 8; + +public: + BCAlgorithm(); + virtual ~BCAlgorithm() {} + + virtual void addDistributions(SPtr<DistributionArray3D> distributions) = 0; + void setNodeIndex(int x1, int x2, int x3); + void setBcPointer(SPtr<BoundaryConditions> bcPtr); + void setCompressible(bool c); + void setCollFactor(LBMReal cf); + char getType(); + bool isPreCollision(); + virtual SPtr<BCAlgorithm> clone() = 0; + SPtr<BCArray3D> getBcArray(); + void setBcArray(SPtr<BCArray3D> bcarray); + virtual void applyBC() = 0; + +protected: + bool compressible; + char type; + bool preCollision; + + SPtr<BoundaryConditions> bcPtr; + SPtr<DistributionArray3D> distributions; + SPtr<BCArray3D> bcArray; + + LBMReal collFactor; + int x1, x2, x3; + + LBMReal compressibleFactor; + + typedef void(*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/); + typedef LBMReal(*CalcFeqForDirFct)(const int& /*direction*/, const LBMReal& /*(d)rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/); + typedef void(*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/, const LBMReal& /*rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/); + + CalcFeqForDirFct calcFeqsForDirFct ; + CalcMacrosFct calcMacrosFct; + CalcFeqFct calcFeqFct; +}; + + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/BCArray3D.cpp b/VirtualFluidsCore/BoundaryConditions/BCArray3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10fe50523d7e96da3cce3461703c466d0c513ddf --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCArray3D.cpp @@ -0,0 +1,235 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCArray3D.cpp +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#include "BCArray3D.h" + +const int BCArray3D::SOLID = -1; +const int BCArray3D::FLUID = -2; +const int BCArray3D::INTERFACECF = -3; +const int BCArray3D::INTERFACEFC = -4; +const int BCArray3D::UNDEFINED = -5; + +////////////////////////////////////////////////////////////////////////// +BCArray3D::BCArray3D() {} +////////////////////////////////////////////////////////////////////////// +BCArray3D::BCArray3D(std::size_t nx1, std::size_t nx2, std::size_t nx3) +{ + bcindexmatrix.resize(nx1, nx2, nx3, UNDEFINED); +} +////////////////////////////////////////////////////////////////////////// +BCArray3D::BCArray3D(std::size_t nx1, std::size_t nx2, std::size_t nx3, int val) +{ + bcindexmatrix.resize(nx1, nx2, nx3, val); +} +////////////////////////////////////////////////////////////////////////// +BCArray3D::~BCArray3D() {} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::resize(std::size_t nx1, std::size_t nx2, std::size_t nx3) +{ + bcindexmatrix.resize(nx1, nx2, nx3); +} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::resize(std::size_t nx1, std::size_t nx2, std::size_t nx3, int val) +{ + bcindexmatrix.resize(nx1, nx2, nx3, val); +} +////////////////////////////////////////////////////////////////////////// +bool BCArray3D::validIndices(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + if (x1 < 0 || x1 >= this->bcindexmatrix.getNX1()) return false; + if (x2 < 0 || x2 >= this->bcindexmatrix.getNX2()) return false; + if (x3 < 0 || x3 >= this->bcindexmatrix.getNX3()) return false; + return true; +} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::setBC(std::size_t x1, std::size_t x2, std::size_t x3, SPtr<BoundaryConditions> const& bc) +{ + if (this->hasBC(x1, x2, x3)) + { + if (this->getBC(x1, x2, x3) == bc) return; + else this->deleteBC(x1, x2, x3); + } + + //if no vacant BCs available + if (indexContainer.empty()) + { + bcvector.push_back(bc); + bcindexmatrix(x1, x2, x3) = (int)bcvector.size() - 1; + } + else + { + int index = indexContainer.back(); + bcindexmatrix(x1, x2, x3) = index; + bcvector[index] = bc; + indexContainer.pop_back(); + } +} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::setSolid(std::size_t x1, std::size_t x2, std::size_t x3) +{ + if (this->hasBC(x1, x2, x3)) this->deleteBC(x1, x2, x3); + bcindexmatrix(x1, x2, x3) = SOLID; +} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::setFluid(std::size_t x1, std::size_t x2, std::size_t x3) +{ + if (this->hasBC(x1, x2, x3)) this->deleteBC(x1, x2, x3); + bcindexmatrix(x1, x2, x3) = FLUID; +} +////////////////////////////////////////////////////////////////////////// +void BCArray3D::setUndefined(std::size_t x1, std::size_t x2, std::size_t x3) +{ + if (this->hasBC(x1, x2, x3)) this->deleteBC(x1, x2, x3); + bcindexmatrix(x1, x2, x3) = UNDEFINED; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getNumberOfSolidEntries() const +{ + const std::vector<int>& data = bcindexmatrix.getDataVector(); + std::size_t counter = 0; + for (std::size_t i = 0; i < data.size(); i++) + if (data[i] == SOLID) counter++; + return counter; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getNumberOfFluidEntries() const +{ + const std::vector<int>& data = bcindexmatrix.getDataVector(); + std::size_t counter = 0; + for (std::size_t i = 0; i < data.size(); i++) + { + int tmp = data[i]; + if (tmp == FLUID || tmp >= 0) counter++; + } + return counter; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getNumberOfFluidWithoutBCEntries() const +{ + const std::vector<int>& data = bcindexmatrix.getDataVector(); + std::size_t counter = 0; + for (std::size_t i = 0; i < data.size(); i++) + if (data[i] == FLUID) counter++; + return counter; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getNumberOfBCEntries() const +{ + const std::vector<int>& data = bcindexmatrix.getDataVector(); + std::size_t counter = 0; + for (std::size_t i = 0; i < data.size(); i++) + if (data[i] >= 0) counter++; + return counter; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getNumberOfUndefinedEntries() const +{ + const std::vector<int>& data = bcindexmatrix.getDataVector(); + std::size_t counter = 0; + for (std::size_t i = 0; i < data.size(); i++) + if (data[i] == UNDEFINED) counter++; + return counter; +} +////////////////////////////////////////////////////////////////////////// +std::size_t BCArray3D::getBCVectorSize() const +{ + return this->bcvector.size(); +} +////////////////////////////////////////////////////////////////////////// +std::string BCArray3D::toString() const +{ + std::size_t solidCounter = 0; + std::size_t fluidCounter = 0; + std::size_t bcCounter = 0; + std::size_t undefCounter = 0; + + for (int x1 = 0; x1 < bcindexmatrix.getNX1(); x1++) + { + for (int x2 = 0; x2 < bcindexmatrix.getNX2(); x2++) + { + for (int x3 = 0; x3 < bcindexmatrix.getNX3(); x3++) + { + if (bcindexmatrix(x1, x2, x3) >= 0) bcCounter++; + else if (bcindexmatrix(x1, x2, x3) == FLUID) fluidCounter++; + else if (bcindexmatrix(x1, x2, x3) == SOLID) solidCounter++; + else if (bcindexmatrix(x1, x2, x3) == UNDEFINED) undefCounter++; + else throw UbException(UB_EXARGS, "invalid matrixEntry"); + } + } + } + + std::size_t unrefEntriesInBcVector = 0; + for (std::size_t i = 0; i < bcvector.size(); i++) if (!bcvector[i]) unrefEntriesInBcVector++; + + std::stringstream text; + text << "BCArray<" << typeid(SPtr<BoundaryConditions>).name() << "," << typeid(int).name() << ">"; + text << "[ entries: " << bcindexmatrix.getNX1() << "x" << bcindexmatrix.getNX2(); + text << "x" << bcindexmatrix.getNX3() << "="; + text << bcindexmatrix.getNX1()*bcindexmatrix.getNX2()*bcindexmatrix.getNX3() << " ]:\n"; + text << " - #fluid entries : " << fluidCounter << std::endl; + text << " - #bc entries : " << bcCounter << std::endl; + text << " - #solid entries : " << solidCounter << std::endl; + text << " - #undef entries : " << undefCounter << std::endl; + text << " - bcvector-entries : " << bcvector.size() << " (empty ones: " << unrefEntriesInBcVector << ")\n"; + text << " - indexContainer-entries: " << indexContainer.size() << std::endl; + + return text.str(); +} +////////////////////////////////////////////////////////////////////////// +std::vector< int >& BCArray3D::getBcindexmatrixDataVector() +{ + return bcindexmatrix.getDataVector(); +} + + +////////////////////////////////////////////////////////////////////////// +void BCArray3D::deleteBCAndSetType(std::size_t x1, std::size_t x2, std::size_t x3, int type) + { + this->deleteBC(x1, x2, x3); + + //Assign matrix to new type + bcindexmatrix(x1, x2, x3) = type; + } +////////////////////////////////////////////////////////////////////////// +void BCArray3D::deleteBC(std::size_t x1, std::size_t x2, std::size_t x3) + { + //check if BC exists at all + int index = bcindexmatrix(x1, x2, x3); + if (index < 0) return; + + //slide the released index into the index container + indexContainer.push_back(index); + + //"delete" element + bcvector[index] = SPtr<BoundaryConditions>(); + } \ No newline at end of file diff --git a/VirtualFluidsCore/BoundaryConditions/BCArray3D.h b/VirtualFluidsCore/BoundaryConditions/BCArray3D.h new file mode 100644 index 0000000000000000000000000000000000000000..b87b03ed33e8a8c2e4e932b591f5cde6164ec101 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCArray3D.h @@ -0,0 +1,224 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCArray3D.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#ifndef BCArray_H +#define BCArray_H + +#include "BoundaryConditions.h" +#include "basics/container/CbArray3D.h" + +#include <typeinfo> + +#include <PointerDefinitions.h> + +//! A class implements array to store boundary conditions flags +class BCArray3D +{ +public: + ////////////////////////////////////////////////////////////////////////// + BCArray3D(); + ////////////////////////////////////////////////////////////////////////// + BCArray3D(std::size_t nx1, std::size_t nx2, std::size_t nx3); + ////////////////////////////////////////////////////////////////////////// + BCArray3D(std::size_t nx1, std::size_t nx2, std::size_t nx3, int val); + ////////////////////////////////////////////////////////////////////////// + virtual ~BCArray3D(); + ////////////////////////////////////////////////////////////////////////// + inline std::size_t getNX1() const; + ////////////////////////////////////////////////////////////////////////// + inline std::size_t getNX2() const; + ////////////////////////////////////////////////////////////////////////// + inline std::size_t getNX3() const; + ////////////////////////////////////////////////////////////////////////// + void resize(std::size_t nx1, std::size_t nx2, std::size_t nx3); + ////////////////////////////////////////////////////////////////////////// + void resize(std::size_t nx1, std::size_t nx2, std::size_t nx3, int val); + ////////////////////////////////////////////////////////////////////////// + bool validIndices(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + inline bool hasBC(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + void setBC(std::size_t x1, std::size_t x2, std::size_t x3, SPtr<BoundaryConditions> const& bc); + ////////////////////////////////////////////////////////////////////////// + inline int getBCVectorIndex(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + inline const SPtr<BoundaryConditions> getBC(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + inline SPtr<BoundaryConditions> getBC(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + void setSolid(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + inline bool isSolid(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + void setFluid(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + //true : FLUID or BC + //false: UNDEFINED or SOLID + inline bool isFluid(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + inline bool isFluidWithoutBC(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + inline bool isUndefined(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + void setUndefined(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + inline bool isInterfaceCF(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + void setInterfaceCF(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + inline bool isInterfaceFC(std::size_t x1, std::size_t x2, std::size_t x3) const; + ////////////////////////////////////////////////////////////////////////// + void setInterfaceFC(std::size_t x1, std::size_t x2, std::size_t x3); + ////////////////////////////////////////////////////////////////////////// + std::size_t getNumberOfSolidEntries() const; + ////////////////////////////////////////////////////////////////////////// + std::size_t getNumberOfFluidEntries() const; + ////////////////////////////////////////////////////////////////////////// + std::size_t getNumberOfFluidWithoutBCEntries() const; + ////////////////////////////////////////////////////////////////////////// + std::size_t getNumberOfBCEntries() const; + ////////////////////////////////////////////////////////////////////////// + std::size_t getNumberOfUndefinedEntries() const; + ////////////////////////////////////////////////////////////////////////// + std::size_t getBCVectorSize() const; + ////////////////////////////////////////////////////////////////////////// + std::string toString() const; + ////////////////////////////////////////////////////////////////////////// + std::vector< int >& getBcindexmatrixDataVector(); + ////////////////////////////////////////////////////////////////////////// + bool isInsideOfDomain(const int &x1, const int &x2, const int &x3, const int& ghostLayerWidth) const; + + static const int SOLID; + static const int FLUID; + static const int INTERFACECF; + static const int INTERFACEFC; + static const int UNDEFINED; + +private: + ////////////////////////////////////////////////////////////////////////// + void deleteBCAndSetType(std::size_t x1, std::size_t x2, std::size_t x3, int type); + ////////////////////////////////////////////////////////////////////////// + void deleteBC(std::size_t x1, std::size_t x2, std::size_t x3); + + friend class MPIIORestartCoProcessor; + friend class MPIIOMigrationCoProcessor; + friend class MPIIOMigrationBECoProcessor; + +protected: + ////////////////////////////////////////////////////////////////////////// + //-1 solid // -2 fluid -... + CbArray3D<int, IndexerX3X2X1> bcindexmatrix; + std::vector<SPtr<BoundaryConditions>> bcvector; + std::vector<int> indexContainer; +}; + + +////////////////////////////////////////////////////////////////////////// +inline std::size_t BCArray3D::getNX1() const { return bcindexmatrix.getNX1(); } +////////////////////////////////////////////////////////////////////////// +inline std::size_t BCArray3D::getNX2() const { return bcindexmatrix.getNX2(); } +////////////////////////////////////////////////////////////////////////// +inline std::size_t BCArray3D::getNX3() const { return bcindexmatrix.getNX3(); } +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::hasBC(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) >= 0; +} +////////////////////////////////////////////////////////////////////////// +inline int BCArray3D::getBCVectorIndex(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3); +} +////////////////////////////////////////////////////////////////////////// +inline const SPtr<BoundaryConditions> BCArray3D::getBC(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + int index = bcindexmatrix(x1, x2, x3); + if (index < 0) return SPtr<BoundaryConditions>(); //=> NULL Pointer + + return bcvector[index]; +} +////////////////////////////////////////////////////////////////////////// +inline SPtr<BoundaryConditions> BCArray3D::getBC(std::size_t x1, std::size_t x2, std::size_t x3) +{ + int index = bcindexmatrix(x1, x2, x3); + if (index < 0) return SPtr<BoundaryConditions>(); //=> NULL Pointer + + return bcvector[index]; +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isSolid(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) == SOLID; +} +////////////////////////////////////////////////////////////////////////// +//true : FLUID or BC +//false: UNDEFINED or SOLID +inline bool BCArray3D::isFluid(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + int tmp = bcindexmatrix(x1, x2, x3); + return (tmp == FLUID || tmp >= 0); +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isFluidWithoutBC(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) == FLUID; +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isUndefined(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) == UNDEFINED; +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isInterfaceCF(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) == INTERFACECF; +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isInterfaceFC(std::size_t x1, std::size_t x2, std::size_t x3) const +{ + return bcindexmatrix(x1, x2, x3) == INTERFACEFC; +} +////////////////////////////////////////////////////////////////////////// +inline bool BCArray3D::isInsideOfDomain(const int& x1, const int& x2, const int& x3, const int& ghostLayerWidth) const +{ + const int minX1 = ghostLayerWidth; + const int maxX1 = (int)this->getNX1() - 1 - ghostLayerWidth; + const int minX2 = ghostLayerWidth; + const int maxX2 = (int)this->getNX2() - 1 - ghostLayerWidth; + const int minX3 = ghostLayerWidth; + const int maxX3 = (int)this->getNX3() - 1 - ghostLayerWidth; + + return (!(x1 < minX1 || x1 > maxX1 || x2 < minX2 || x2 > maxX2 || x3 < minX3 || x3 > maxX3)); +} + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/BCFunction.cpp b/VirtualFluidsCore/BoundaryConditions/BCFunction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f661804b17bf64d5e5f8217f9947f816aeb7db9 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCFunction.cpp @@ -0,0 +1,38 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCFunction.cpp +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#include "BCFunction.h" + +const double BCFunction::INFTIMEDEPENDENT = -1.0; +const double BCFunction::INFCONST = -10.0; + diff --git a/VirtualFluidsCore/BoundaryConditions/BCFunction.h b/VirtualFluidsCore/BoundaryConditions/BCFunction.h new file mode 100644 index 0000000000000000000000000000000000000000..0f9ad2f342efaf5cd6eaa29b348b5e9f76a714a4 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCFunction.h @@ -0,0 +1,113 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCFunction.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#ifndef D3Q27BCFUNCTION_H +#define D3Q27BCFUNCTION_H + +#include <basics/utilities/UbInfinity.h> + +#include <MuParser/include/muParser.h> + +//! A class implements function parcer for boundary conditions +class BCFunction +{ +public: + static const double INFTIMEDEPENDENT; + static const double INFCONST; + +public: + BCFunction() + : starttime(-Ub::inf ), endtime(-Ub::inf ) + { + + } + BCFunction( const mu::Parser& function, const double& starttime, const double& endtime ) + : function(function), starttime(starttime), endtime(endtime) + { + + } + BCFunction( const std::string& functionstring, const double& starttime, const double& endtime ) + : starttime(starttime), endtime(endtime) + { + this->setFunction(functionstring); + } + BCFunction( const double& velocity, const double& starttime, const double& endtime ) + : starttime(starttime), endtime(endtime) + { + this->setFunction(velocity); + } + + void setFunction(const mu::Parser& function) { this->function = function; } + void setFunction(const std::string& functionstring) { this->function.SetExpr(functionstring); } + void setFunction(const double& constVelocity) { std::stringstream dummy; dummy<<constVelocity; function.SetExpr(dummy.str()); } + void setStartTime(const double& starttime) {this->starttime = starttime; } + void setEndTime(const double& starttime) {this->endtime = endtime; } + + mu::Parser& getFunction() { return function; } + const mu::Parser& getFunction() const { return function; } + const double& getStartTime() const { return starttime; } + const double& getEndTime() const { return endtime; } + + std::string toString() const + { + std::stringstream info; + if (starttime==INFTIMEDEPENDENT) info<<"start=inf. timedep., "; + else if(starttime==INFCONST ) info<<"start=inf. const., "; + else info<<"start="<<starttime<<", "; + if (endtime==INFTIMEDEPENDENT) info<<"end=inf. timedep."<<std::endl; + else if(endtime==INFCONST ) info<<"end=inf. const."<<std::endl; + else info<<"end="<<endtime<<std::endl; + info<<"expr="<<function.GetExpr()<<std::endl; + info<<"with constants: "; + mu::valmap_type cmap = function.GetConst(); + for(mu::valmap_type::const_iterator item = cmap.begin(); item!=cmap.end(); ++item) + info<<item->first<<"="<<item->second<<", "; + return info.str(); + } + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, const BCFunction& bc) + { + os<<bc.toString(); + return os; + } + +protected: + mu::Parser function; + double starttime; + double endtime; + +private: + +}; + +#endif //D3Q27BCFUNCTION_H diff --git a/VirtualFluidsCore/BoundaryConditions/BCProcessor.cpp b/VirtualFluidsCore/BoundaryConditions/BCProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5eabfe8eedc25d9fd720ab34a1c16dff874774ee --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCProcessor.cpp @@ -0,0 +1,102 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCProcessor.h +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#include "BCProcessor.h" +#include "D3Q27EsoTwist3DSplittedVector.h" +#include "DataSet3D.h" +#include "ILBMKernel.h" +#include "BCArray3D.h" +#include "BCAlgorithm.h" + +BCProcessor::BCProcessor() +{ + +} +////////////////////////////////////////////////////////////////////////// +BCProcessor::BCProcessor(SPtr<ILBMKernel> kernel) +{ + SPtr<DistributionArray3D> distributions = std::dynamic_pointer_cast<EsoTwist3D>(kernel->getDataSet()->getFdistributions()); + bcArray = SPtr<BCArray3D>(new BCArray3D( distributions->getNX1(), distributions->getNX2(), distributions->getNX3(), BCArray3D::FLUID)); +} +////////////////////////////////////////////////////////////////////////// +BCProcessor::~BCProcessor() +{ + +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCProcessor> BCProcessor::clone(SPtr<ILBMKernel> kernel) +{ + SPtr<BCProcessor> bcProcessor(new BCProcessor(kernel)); + return bcProcessor; +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCArray3D> BCProcessor::getBCArray() +{ + return bcArray; +} +////////////////////////////////////////////////////////////////////////// +void BCProcessor::setBCArray(SPtr<BCArray3D> bcarray) +{ + bcArray = bcarray; +} +////////////////////////////////////////////////////////////////////////// +void BCProcessor::addBC(SPtr<BCAlgorithm> bc) +{ + if (bc->isPreCollision()) + { + preBC.push_back(bc); + } + else + { + postBC.push_back(bc); + } +} +////////////////////////////////////////////////////////////////////////// +void BCProcessor::applyPreCollisionBC() +{ + for(SPtr<BCAlgorithm> bc : preBC) + bc->applyBC(); +} +////////////////////////////////////////////////////////////////////////// +void BCProcessor::applyPostCollisionBC() +{ + for (SPtr<BCAlgorithm> bc : postBC) + bc->applyBC(); +} +////////////////////////////////////////////////////////////////////////// +void BCProcessor::clearBC() +{ + preBC.clear(); + postBC.clear(); +} + diff --git a/VirtualFluidsCore/BoundaryConditions/BCProcessor.h b/VirtualFluidsCore/BoundaryConditions/BCProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..9dc572b0d11df350846bc8f17b62bb57f356dc36 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BCProcessor.h @@ -0,0 +1,68 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BCProcessor.h +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BC_PROCESSSOR_H +#define BC_PROCESSSOR_H + +#include <PointerDefinitions.h> +#include <vector> + +class BCArray3D; +class BCAlgorithm; +class ILBMKernel; + +//! A class provides an interface for boundary conditions in the calculation loop. +class BCProcessor +{ +public: + BCProcessor(); + BCProcessor(SPtr<ILBMKernel> kernel); + virtual ~BCProcessor(); + virtual SPtr<BCArray3D> getBCArray(); + virtual void setBCArray(SPtr<BCArray3D> bcarray); + virtual SPtr<BCProcessor> clone(SPtr<ILBMKernel> kernel); + + void addBC(SPtr<BCAlgorithm> bc); + void applyPreCollisionBC(); + void applyPostCollisionBC(); + void clearBC(); +protected: + std::vector<SPtr<BCAlgorithm> > preBC; + std::vector<SPtr<BCAlgorithm> > postBC; + SPtr<BCArray3D> bcArray; + +private: + +}; + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.cpp b/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dadd850f73b3ec678f30692bc2884c811f25144 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.cpp @@ -0,0 +1,37 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BoundaryConditions.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#include "BoundaryConditions.h" + +const long long BoundaryConditions::maxOptionVal = ( 1<<optionDigits ) - 1; //2^3-1 -> 7 + diff --git a/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.h b/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.h new file mode 100644 index 0000000000000000000000000000000000000000..e9131f4f15374705bf1efd408ca8c070c6884ea4 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/BoundaryConditions.h @@ -0,0 +1,283 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BoundaryConditions.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= +#ifndef BoundaryConditions_H +#define BoundaryConditions_H + +#include <vector> +#include <string> + +#include "Vector3D.h" +#include "UbException.h" +#include "UbSystem.h" +#include "UbTuple.h" +#include "D3Q27System.h" +#include <PointerDefinitions.h> + +//! Difenition of baundary conditions in grid generation +class BoundaryConditions +{ +public: + BoundaryConditions() + : noslipBoundaryFlags(0) + , slipBoundaryFlags(0) + , velocityBoundaryFlags(0) + , densityBoundaryFlags(0) + , wallModelBoundaryFlags(0) + , bcVelocityX1(0.0f) + , bcVelocityX2(0.0f) + , bcVelocityX3(0.0f) + , bcDensity(0.0f) + , bcLodiDensity(0.0f) + , bcLodiVelocityX1(0.0f) + , bcLodiVelocityX2(0.0f) + , bcLodiVelocityX3(0.0f) + , bcLodiLentgh(0.0f) + , nx1(0.0f) + , nx2(0.0f) + , nx3(0.0f) + , algorithmType(-1) + { + UB_STATIC_ASSERT( sizeof(long long) >= 8); + UB_STATIC_ASSERT( (sizeof(long long)*8) >= (D3Q27System::FENDDIR+1)*BoundaryConditions::optionDigits ); + + for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) + q[fdir] = -999.; + } + virtual ~BoundaryConditions() {} + + virtual bool isEmpty() { return (noslipBoundaryFlags&slipBoundaryFlags&velocityBoundaryFlags&densityBoundaryFlags)==0;} + virtual bool hasBoundaryCondition() + { + return ( hasNoSlipBoundary() || hasSlipBoundary() + || hasDensityBoundary() || hasVelocityBoundary() || hasWallModelBoundary() ); + } + + virtual bool hasBoundaryConditionFlag(const int& direction) + { + assert( direction >= D3Q27System::FSTARTDIR && direction <= D3Q27System::FENDDIR ); + + return ( hasNoSlipBoundaryFlag(direction) || hasSlipBoundaryFlag(direction) + || hasDensityBoundaryFlag(direction) || hasVelocityBoundaryFlag(direction) || hasWallModelBoundaryFlag(direction)); + } +protected: + void setFlagBits(long long& flag, const int& direction, const short& secOpt) + { + if( (secOpt+1)>maxOptionVal ) + throw UbException(UB_EXARGS,"error: option > "+UbSystem::toString(maxOptionVal-1)); + + //all digits at the respective positions to "0" + flag &= ~( maxOptionVal<<(direction*optionDigits) ); + //set all digits according to the flag at the respective positions + flag |= ((long long)(secOpt+1)<<(direction*optionDigits)); + } +public: + /*===================== NoSlip Boundary ==================================================*/ + void setNoSlipBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(noslipBoundaryFlags,direction,secOpt); } + void unsetNoSlipBoundaryFlag(const int& direction) { this->noslipBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) ); } + void unsetNoSlipBoundary() { this->noslipBoundaryFlags = 0; } + long long getNoSlipBoundary() { return this->noslipBoundaryFlags; } + bool hasNoSlipBoundary() { return (noslipBoundaryFlags!=0); } + bool hasNoSlipBoundaryFlag(const int& direction) { return ( ( ( noslipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0); } + short getNoSlipSecondaryOption(const int& direction) { return (short)( ( ( noslipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); } + /*===================== WallModel Boundary ==================================================*/ + void setWallModelBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(wallModelBoundaryFlags,direction,secOpt); } + void unsetWallModelBoundaryFlag(const int& direction) { this->wallModelBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) ); } + void unsetWallModelBoundary() { this->wallModelBoundaryFlags = 0; } + long long getWallModelBoundary() { return this->wallModelBoundaryFlags; } + bool hasWallModelBoundary() { return (wallModelBoundaryFlags!=0); } + bool hasWallModelBoundaryFlag(const int& direction) { return ( ( ( wallModelBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0); } + short getWallModelSecondaryOption(const int& direction) { return (short)( ( ( wallModelBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); } + /*===================== Slip-Solid Boundary ==================================================*/ + void setSlipBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(slipBoundaryFlags,direction,secOpt); } + void unsetSlipBoundaryFlag(const int& direction) { this->slipBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) ); } + void unsetSlipBoundary() { this->slipBoundaryFlags = 0; } + long long getSlipBoundary() { return this->slipBoundaryFlags; } + bool hasSlipBoundary() { return (slipBoundaryFlags!=0); } + bool hasSlipBoundaryFlag(const int& direction) { return ( ( ( slipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0); } + short getSlipSecondaryOption(const int& direction) { return (short)( ( ( slipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); } + void setNormalVector(const LBMReal& nx1,const LBMReal& nx2,const LBMReal& nx3) { this->nx1 = nx1; this->nx2 = nx2; this->nx3 = nx3;} + UbTupleDouble3 getNormalVector() { return makeUbTuple(nx1,nx2,nx3); } + + /*============== Velocity Boundary ========================*/ + void setVelocityBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(velocityBoundaryFlags,direction,secOpt); } + void unsetVelocityBoundaryFlag(const int& direction) { this->velocityBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) ); } + void unsetVelocityBoundary() { this->velocityBoundaryFlags = 0; } + long long getVelocityBoundary() { return this->velocityBoundaryFlags; } + bool hasVelocityBoundary() { return this->velocityBoundaryFlags!=0; } + bool hasVelocityBoundaryFlag(const int& direction) { return ( ( ( velocityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0); } + short getVelocitySecondaryOption(const int& direction) { return (short)( ( ( velocityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); } + + void setBoundaryVelocity(const Vector3D& vx) + { + setBoundaryVelocityX1((LBMReal)vx[0]); + setBoundaryVelocityX2((LBMReal)vx[1]); + setBoundaryVelocityX3((LBMReal)vx[2]); + } + void setBoundaryVelocityX1(const LBMReal& vx1) { this->bcVelocityX1 = vx1; } + void setBoundaryVelocityX2(const LBMReal& vx2) { this->bcVelocityX2 = vx2; } + void setBoundaryVelocityX3(const LBMReal& vx3) { this->bcVelocityX3 = vx3; } + LBMReal getBoundaryVelocityX1() { return this->bcVelocityX1; } + LBMReal getBoundaryVelocityX2() { return this->bcVelocityX2; } + LBMReal getBoundaryVelocityX3() { return this->bcVelocityX3; } + LBMReal getBoundaryVelocity(const int& direction) + { + switch(direction) + { + case D3Q27System::E : return (LBMReal)( UbMath::c4o9*(+bcVelocityX1) ); //(2/cs^2)(=6)*rho_0(=1 for incompressible)*wi*u*ei with cs=1/sqrt(3) + case D3Q27System::W : return (LBMReal)( UbMath::c4o9*(-bcVelocityX1) ); + case D3Q27System::N : return (LBMReal)( UbMath::c4o9*(+bcVelocityX2) ); + case D3Q27System::S : return (LBMReal)( UbMath::c4o9*(-bcVelocityX2) ); + case D3Q27System::T : return (LBMReal)( UbMath::c4o9*(+bcVelocityX3) ); + case D3Q27System::B : return (LBMReal)( UbMath::c4o9*(-bcVelocityX3) ); + case D3Q27System::NE: return (LBMReal)( UbMath::c1o9*(+bcVelocityX1+bcVelocityX2 ) ); + case D3Q27System::SW: return (LBMReal)( UbMath::c1o9*(-bcVelocityX1-bcVelocityX2 ) ); + case D3Q27System::SE: return (LBMReal)( UbMath::c1o9*(+bcVelocityX1-bcVelocityX2 ) ); + case D3Q27System::NW: return (LBMReal)( UbMath::c1o9*(-bcVelocityX1+bcVelocityX2 ) ); + case D3Q27System::TE: return (LBMReal)( UbMath::c1o9*(+bcVelocityX1 +bcVelocityX3) ); + case D3Q27System::BW: return (LBMReal)( UbMath::c1o9*(-bcVelocityX1 -bcVelocityX3) ); + case D3Q27System::BE: return (LBMReal)( UbMath::c1o9*(+bcVelocityX1 -bcVelocityX3) ); + case D3Q27System::TW: return (LBMReal)( UbMath::c1o9*(-bcVelocityX1 +bcVelocityX3) ); + case D3Q27System::TN: return (LBMReal)( UbMath::c1o9*( +bcVelocityX2+bcVelocityX3) ); + case D3Q27System::BS: return (LBMReal)( UbMath::c1o9*( -bcVelocityX2-bcVelocityX3) ); + case D3Q27System::BN: return (LBMReal)( UbMath::c1o9*( +bcVelocityX2-bcVelocityX3) ); + case D3Q27System::TS: return (LBMReal)( UbMath::c1o9*( -bcVelocityX2+bcVelocityX3) ); + case D3Q27System::TNE: return (LBMReal)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2+bcVelocityX3) ); + case D3Q27System::BSW: return (LBMReal)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2-bcVelocityX3) ); + case D3Q27System::BNE: return (LBMReal)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2-bcVelocityX3) ); + case D3Q27System::TSW: return (LBMReal)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2+bcVelocityX3) ); + case D3Q27System::TSE: return (LBMReal)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2+bcVelocityX3) ); + case D3Q27System::BNW: return (LBMReal)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2-bcVelocityX3) ); + case D3Q27System::BSE: return (LBMReal)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2-bcVelocityX3) ); + case D3Q27System::TNW: return (LBMReal)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2+bcVelocityX3) ); + default: throw UbException(UB_EXARGS,"unknown error"); + } + } + + /*============== Density Boundary ========================*/ + void setDensityBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(densityBoundaryFlags,direction,secOpt); } + void unsetDensityBoundaryFlag(const int& direction) { this->densityBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) ); } + void unsetDensityBoundary() { this->densityBoundaryFlags = 0; } + long long getDensityBoundary() { return this->densityBoundaryFlags; } + bool hasDensityBoundary() { return (this->densityBoundaryFlags!=0); } + bool hasDensityBoundaryFlag(const int& direction) { return ( ( ( densityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0); } + short getDensitySecondaryOption(const int& direction) { return (short)( ( ( densityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); } + + void setBoundaryDensity(LBMReal density) { this->bcDensity = density; } + LBMReal getBoundaryDensity() { return this->bcDensity; } + + //Lodi extension + void setDensityLodiDensity(const LBMReal& bcLodiDensity) { this->bcLodiDensity = bcLodiDensity; } + void setDensityLodiVelocityX1(const LBMReal& bcLodiVelocityX1) { this->bcLodiVelocityX1 = bcLodiVelocityX1; } + void setDensityLodiVelocityX2(const LBMReal& bcLodiVelocityX2) { this->bcLodiVelocityX2 = bcLodiVelocityX2; } + void setDensityLodiVelocityX3(const LBMReal& bcLodiVelocityX3) { this->bcLodiVelocityX3 = bcLodiVelocityX3; } + void setDensityLodiLength(const LBMReal& bcLodiLentgh) { this->bcLodiLentgh = bcLodiLentgh; } + LBMReal getDensityLodiDensity() const { return this->bcLodiDensity; } + LBMReal getDensityLodiVelocityX1() const { return this->bcLodiVelocityX1; } + LBMReal getDensityLodiVelocityX2() const { return this->bcLodiVelocityX2; } + LBMReal getDensityLodiVelocityX3() const { return this->bcLodiVelocityX3; } + LBMReal getDensityLodiLength() const { return this->bcLodiLentgh; } + + LBMReal& densityLodiDensity() { return this->bcLodiDensity; } + LBMReal& densityLodiVelocityX1() { return this->bcLodiVelocityX1; } + LBMReal& densityLodiVelocityX2() { return this->bcLodiVelocityX2; } + LBMReal& densityLodiVelocityX3() { return this->bcLodiVelocityX3; } + LBMReal& densityLodiLentgh() { return this->bcLodiLentgh; } + + const LBMReal& densityLodiDensity() const { return this->bcLodiDensity; } + const LBMReal& densityLodiVelocityX1() const { return this->bcLodiVelocityX1; } + const LBMReal& densityLodiVelocityX2() const { return this->bcLodiVelocityX2; } + const LBMReal& densityLodiVelocityX3() const { return this->bcLodiVelocityX3; } + const LBMReal& densityLodiLentgh() const { return this->bcLodiLentgh; } + + + /*======================= Qs =============================*/ + void setQ(const LBMReal& val, const int& direction) { q[direction] = val; } + LBMReal getQ(const int& direction) { return q[direction]; } + + virtual std::vector< std::string > getBCNames() + { + std::vector< std::string > tmp; + tmp.push_back( "NoSlipBC" ); + tmp.push_back( "SlipBC" ); + tmp.push_back( "VelocityBC" ); + tmp.push_back( "DensityBC" ); + return tmp; + } + virtual std::vector< long long > getBCFlags() + { + std::vector< long long > tmp; + tmp.push_back( noslipBoundaryFlags ); + tmp.push_back( slipBoundaryFlags ); + tmp.push_back( velocityBoundaryFlags ); + tmp.push_back( densityBoundaryFlags ); + return tmp; + } + + static bool hasFlagForDirection(const long long& flag, const int& direction) + { + return ( ( ( flag>>(optionDigits*direction) ) & maxOptionVal ) != 0); + } + + void setBcAlgorithmType(char alg) { algorithmType = alg; } + char getBcAlgorithmType() { return algorithmType; } + +public: + static const int optionDigits = 2; //--> 2 bits for secondary Option --> maxOptionVal = 7 + static const long long maxOptionVal;// = ( 1<<optionDigits ) - 1; //2^3-1 -> 7 + +protected: + LBMReal q[D3Q27System::FENDDIR+1]; + + long long noslipBoundaryFlags; + long long slipBoundaryFlags; + long long velocityBoundaryFlags; + long long densityBoundaryFlags; + long long wallModelBoundaryFlags; + + LBMReal bcVelocityX1; + LBMReal bcVelocityX2; + LBMReal bcVelocityX3; + LBMReal bcDensity; + + LBMReal bcLodiDensity; + LBMReal bcLodiVelocityX1; + LBMReal bcLodiVelocityX2; + LBMReal bcLodiVelocityX3; + LBMReal bcLodiLentgh; + + LBMReal nx1,nx2,nx3; + + char algorithmType; +}; + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/CMakePackage.txt b/VirtualFluidsCore/BoundaryConditions/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..e3e3f9a387b022a62ecc0d63c3ef0210313e906d --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) \ No newline at end of file diff --git a/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.cpp b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58e479e39b3e71c291c95a435b7d2ed09c4b5aa3 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.cpp @@ -0,0 +1,33 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NoSlipBCAdapter.cpp +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= +#include "NoSlipBCAdapter.h" diff --git a/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.h b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.h new file mode 100644 index 0000000000000000000000000000000000000000..5a09aefb44bed939467023825b7e4fbece3a9ab8 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAdapter.h @@ -0,0 +1,68 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NoSlipBCAdapter.cpp +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#ifndef NoSlipBCAdapter_H +#define NoSlipBCAdapter_H + +#include "BCAdapter.h" + +//! A class provides an interface for no-slip boundary condition in grid generator +class NoSlipBCAdapter : public BCAdapter +{ +public: + NoSlipBCAdapter() + : BCAdapter() + { + } + NoSlipBCAdapter(const short& secondaryBcOption) + : BCAdapter(secondaryBcOption) + { + } + + void init(const D3Q27Interactor* const& interactor, const double& time=0) {} + void update(const D3Q27Interactor* const& interactor, const double& time=0) {} + + void adaptBCForDirection( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 ) + { + bc->setNoSlipBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption); + bc->setQ((float)q,fdirection); + } + void adaptBC( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 ) + { + bc->setBcAlgorithmType(algorithmType); + } + +private: + +}; +#endif //NoSlipBCAdapter_H diff --git a/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.cpp b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b68bf910f903d2c6c3ad839d02d64aff4ce83cc --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.cpp @@ -0,0 +1,80 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NoSlipBCAlgorithm.cpp +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#include "NoSlipBCAlgorithm.h" +#include "DistributionArray3D.h" +#include "BoundaryConditions.h" + +NoSlipBCAlgorithm::NoSlipBCAlgorithm() +{ + BCAlgorithm::type = BCAlgorithm::NoSlipBCAlgorithm; + BCAlgorithm::preCollision = false; +} +////////////////////////////////////////////////////////////////////////// +NoSlipBCAlgorithm::~NoSlipBCAlgorithm() +{ + +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCAlgorithm> NoSlipBCAlgorithm::clone() +{ + SPtr<BCAlgorithm> bc(new NoSlipBCAlgorithm()); + return bc; +} +////////////////////////////////////////////////////////////////////////// +void NoSlipBCAlgorithm::addDistributions(SPtr<DistributionArray3D> distributions) +{ + this->distributions = distributions; +} +////////////////////////////////////////////////////////////////////////// +void NoSlipBCAlgorithm::applyBC() +{ + LBMReal f[D3Q27System::ENDF+1]; + LBMReal feq[D3Q27System::ENDF+1]; + distributions->getDistributionInv(f, x1, x2, x3); + LBMReal rho, vx1, vx2, vx3; + calcMacrosFct(f, rho, vx1, vx2, vx3); + calcFeqFct(feq, rho, vx1, vx2, vx3); + + for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) + { + if (bcPtr->hasNoSlipBoundaryFlag(fdir)) + { + //quadratic bounce back + const int invDir = D3Q27System::INVDIR[fdir]; + LBMReal q = bcPtr->getQ(invDir); + LBMReal fReturn = ((1.0-q)/(1.0+q))*((f[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q/(1.0+q))*(f[invDir]+f[fdir])); + distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir); + } + } +} diff --git a/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.h b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..1cf6d64203bcb5c77f39c3dc717a32e731f21516 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/NoSlipBCAlgorithm.h @@ -0,0 +1,53 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NoSlipBCAlgorithm.h +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef NoSlipBCAlgorithm_h__ +#define NoSlipBCAlgorithm_h__ + +#include "BCAlgorithm.h" +#include <PointerDefinitions.h> + +class DistributionArray3D; + +//! A class implements no-slip boundary condition +class NoSlipBCAlgorithm : public BCAlgorithm +{ +public: + NoSlipBCAlgorithm(); + virtual ~NoSlipBCAlgorithm(); + SPtr<BCAlgorithm> clone(); + void addDistributions(SPtr<DistributionArray3D> distributions); + void applyBC() override; +private: +}; +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.cpp b/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7089da4e4b4a7d26df35fa91a01edbb487752a1c --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.cpp @@ -0,0 +1,339 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VelocityBCAdapter.cpp +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= + +#include "VelocityBCAdapter.h" +#include "basics/utilities/UbLogger.h" +#include "basics/utilities/UbMath.h" +#include "basics/utilities/UbTuple.h" + +using namespace std; + + +VelocityBCAdapter::VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const BCFunction& velVxBC) +{ + if(vx1) this->vx1BCs.push_back(velVxBC); + if(vx2) this->vx2BCs.push_back(velVxBC); + if(vx3) this->vx3BCs.push_back(velVxBC); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function, const double& startTime, const double& endTime ) +{ + if(vx1) this->vx1BCs.push_back(BCFunction(function,startTime,endTime)); + if(vx2) this->vx2BCs.push_back(BCFunction(function,startTime,endTime)); + if(vx3) this->vx3BCs.push_back(BCFunction(function,startTime,endTime)); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function1, const mu::Parser& function2, const mu::Parser& function3, const double& startTime, const double& endTime ) +{ + if(vx1) this->vx1BCs.push_back(BCFunction(function1,startTime,endTime)); + if(vx2) this->vx2BCs.push_back(BCFunction(function2,startTime,endTime)); + if(vx3) this->vx3BCs.push_back(BCFunction(function3,startTime,endTime)); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const string& functionstring, const double& startTime, const double& endTime ) +{ + if(vx1) this->vx1BCs.push_back(BCFunction(functionstring,startTime,endTime)); + if(vx2) this->vx2BCs.push_back(BCFunction(functionstring,startTime,endTime)); + if(vx3) this->vx3BCs.push_back(BCFunction(functionstring,startTime,endTime)); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const BCFunction& velBC, bool x1Dir, bool x2Dir, bool x3Dir) +{ + if(x1Dir) this->vx1BCs.push_back(velBC); + if(x2Dir) this->vx2BCs.push_back(velBC); + if(x3Dir) this->vx3BCs.push_back(velBC); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const BCFunction& velVx1BC, const BCFunction& velVx2BC, const BCFunction& velVx3BC) +{ + if( velVx1BC.getEndTime()!=-Ub::inf ) this->vx1BCs.push_back(velVx1BC); + if( velVx2BC.getEndTime()!=-Ub::inf ) this->vx2BCs.push_back(velVx2BC); + if( velVx3BC.getEndTime()!=-Ub::inf ) this->vx3BCs.push_back(velVx3BC); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const vector< BCFunction >& velVx1BCs, const vector< BCFunction >& velVx2BCs, const vector< BCFunction >& velVx3BCs) +{ + this->vx1BCs = velVx1BCs; + this->vx2BCs = velVx2BCs; + this->vx3BCs = velVx3BCs; + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const double& vx1, const double& vx1StartTime, const double& vx1EndTime, + const double& vx2, const double& vx2StartTime, const double& vx2EndTime, + const double& vx3, const double& vx3StartTime, const double& vx3EndTime ) +{ + this->vx1BCs.push_back(BCFunction(vx1,vx1StartTime,vx1EndTime)); + this->vx2BCs.push_back(BCFunction(vx2,vx2StartTime,vx2EndTime)); + this->vx3BCs.push_back(BCFunction(vx3,vx3StartTime,vx3EndTime)); + this->init(); +} +/*==========================================================*/ +VelocityBCAdapter::VelocityBCAdapter(const string& vx1Function, const double& vx1StartTime, const double& vx1EndTime, + const string& vx2Function, const double& vx2StartTime, const double& vx2EndTime, + const string& vx3Function, const double& vx3StartTime, const double& vx3EndTime ) +{ + if(vx1Function.size()) this->vx1BCs.push_back(BCFunction(vx1Function,vx1StartTime,vx1EndTime)); + if(vx2Function.size()) this->vx2BCs.push_back(BCFunction(vx2Function,vx2StartTime,vx2EndTime)); + if(vx3Function.size()) this->vx3BCs.push_back(BCFunction(vx3Function,vx3StartTime,vx3EndTime)); + this->init(); +} +/*==========================================================*/ +void VelocityBCAdapter::setNewVelocities(const double& vx1, const double& vx1StartTime, const double& vx1EndTime, + const double& vx2, const double& vx2StartTime, const double& vx2EndTime, + const double& vx3, const double& vx3StartTime, const double& vx3EndTime ) +{ + this->clear(); + this->vx1BCs.push_back(BCFunction(vx1,vx1StartTime,vx1EndTime)); + this->vx2BCs.push_back(BCFunction(vx2,vx2StartTime,vx2EndTime)); + this->vx3BCs.push_back(BCFunction(vx3,vx3StartTime,vx3EndTime)); + this->init(); +} +/*==========================================================*/ +void VelocityBCAdapter::init() +{ + this->unsetTimeDependent(); + + this->timeStep = 0.0; + + this->x1 = 0.0; + this->x2 = 0.0; + this->x3 = 0.0; + + this->tmpVx1Function = NULL; + this->tmpVx2Function = NULL; + this->tmpVx3Function = NULL; + + try //initilialization and validation of functions + { + this->init(vx1BCs); + this->init(vx2BCs); + this->init(vx3BCs); + } + catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")" + <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); } + catch(...) { throw UbException(UB_EXARGS,"unknown exception" ); } +} +/*==========================================================*/ +void VelocityBCAdapter::init(std::vector<BCFunction>& vxBCs) +{ + for(size_t pos=0; pos<vxBCs.size(); ++pos) + { + if( !( UbMath::equal( BCFunction::INFCONST, vxBCs[pos].getEndTime() ) + && UbMath::greaterEqual( this->timeStep, vxBCs[pos].getStartTime() ) ) ) + { + this->setTimeDependent(); + } + + vxBCs[pos].getFunction().DefineVar("t" , &this->timeStep); + vxBCs[pos].getFunction().DefineVar("x1", &this->x1 ); + vxBCs[pos].getFunction().DefineVar("x2", &this->x2 ); + vxBCs[pos].getFunction().DefineVar("x3", &this->x3 ); + + vxBCs[pos].getFunction().Eval(); //<-- validation + } +} +/*==========================================================*/ +void VelocityBCAdapter::init(const D3Q27Interactor* const& interactor, const double& time) +{ + this->timeStep = time; + this->tmpVx1Function = this->tmpVx2Function = this->tmpVx3Function = NULL; + + //aktuelle velocityfunction bestimmen + double maxEndtime = -Ub::inf; + + for(size_t pos=0; pos<vx1BCs.size(); ++pos) + { + if( UbMath::equal(vx1BCs[pos].getEndTime(),BCFunction::INFTIMEDEPENDENT) ) maxEndtime=Ub::inf; + maxEndtime = UbMath::max(maxEndtime,vx1BCs[pos].getStartTime(),vx1BCs[pos].getEndTime()); //startTime abfragen, da INFCONST=-10 + + if( UbMath::greaterEqual(this->timeStep,vx1BCs[pos].getStartTime()) ) + { + if( UbMath::lessEqual( this->timeStep , vx1BCs[pos].getEndTime() ) + || UbMath::equal( vx1BCs[pos].getEndTime(), (double)BCFunction::INFCONST ) + || UbMath::equal( vx1BCs[pos].getEndTime(), (double)BCFunction::INFTIMEDEPENDENT) ) + { + tmpVx1Function = &vx1BCs[pos].getFunction(); + break; + } + } + } + for(size_t pos=0; pos<vx2BCs.size(); ++pos) + { + if( UbMath::equal(vx2BCs[pos].getEndTime(),BCFunction::INFTIMEDEPENDENT)) maxEndtime=Ub::inf; + maxEndtime = UbMath::max(maxEndtime,vx2BCs[pos].getStartTime(),vx2BCs[pos].getEndTime()); //startTime abfragen, da INFCONST=-10 + + if( UbMath::greaterEqual(this->timeStep,vx2BCs[pos].getStartTime()) ) + { + if( UbMath::lessEqual( this->timeStep , vx2BCs[pos].getEndTime() ) + || UbMath::equal( vx2BCs[pos].getEndTime(), (double)BCFunction::INFCONST ) + || UbMath::equal( vx2BCs[pos].getEndTime(), (double)BCFunction::INFTIMEDEPENDENT ) ) + { + tmpVx2Function = &vx2BCs[pos].getFunction(); + break; + } + } + } + for(size_t pos=0; pos<vx3BCs.size(); ++pos) + { + if( UbMath::equal(vx3BCs[pos].getEndTime(),BCFunction::INFTIMEDEPENDENT)) maxEndtime=Ub::inf; + maxEndtime = UbMath::max(maxEndtime,vx3BCs[pos].getStartTime(),vx3BCs[pos].getEndTime()); //startTime abfragen, da INFCONST=-10 + + if( UbMath::greaterEqual(this->timeStep,vx3BCs[pos].getStartTime()) ) + { + if( UbMath::lessEqual( this->timeStep , vx3BCs[pos].getEndTime() ) + || UbMath::equal( vx3BCs[pos].getEndTime(), (double)BCFunction::INFCONST ) + || UbMath::equal( vx3BCs[pos].getEndTime(), (double)BCFunction::INFTIMEDEPENDENT ) ) + { + tmpVx3Function = &vx3BCs[pos].getFunction(); + break; + } + } + } + + if( UbMath::greaterEqual(time,maxEndtime) ) + { + if( !this->isTimePeriodic() ) this->unsetTimeDependent(); + else //bei peridoic die interavalle neu setzen: + { + if( UbMath::equal(maxEndtime,BCFunction::INFCONST) ) + for(size_t pos=0; pos<vx1BCs.size(); ++pos) + { + vx1BCs[pos].setStartTime( vx1BCs[pos].getStartTime() + timeStep ); + vx1BCs[pos].setEndTime( vx1BCs[pos].getEndTime() + timeStep ); + } + if( UbMath::equal(maxEndtime,BCFunction::INFCONST) ) + for(size_t pos=0; pos<vx2BCs.size(); ++pos) + { + vx2BCs[pos].setStartTime( vx2BCs[pos].getStartTime() + timeStep ); + vx2BCs[pos].setEndTime( vx2BCs[pos].getEndTime() + timeStep ); + } + if( UbMath::equal(maxEndtime,BCFunction::INFCONST) ) + for(size_t pos=0; pos<vx3BCs.size(); ++pos) + { + vx3BCs[pos].setStartTime( vx3BCs[pos].getStartTime() + timeStep ); + vx3BCs[pos].setEndTime( vx3BCs[pos].getEndTime() + timeStep ); + } + this->init(interactor,time); + } + } + + UBLOG(logDEBUG4,"D3Q27VelocityBCAdapter::init(time="<<time<<") " + <<", vx1= \""<<(tmpVx1Function ? tmpVx1Function->GetExpr() : "-")<<"\"" + <<", vx2= \""<<(tmpVx2Function ? tmpVx2Function->GetExpr() : "-")<<"\"" + <<", vx3= \""<<(tmpVx3Function ? tmpVx3Function->GetExpr() : "-")<<"\"" + <<", timedependent="<<boolalpha<<this->isTimeDependent() ); +} +/*==========================================================*/ +void VelocityBCAdapter::update( const D3Q27Interactor* const& interactor, const double& time ) +{ + this->init(interactor,time); +} +/*==========================================================*/ +void VelocityBCAdapter::adaptBCForDirection( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time ) +{ + bc->setVelocityBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption); + bc->setQ((float)q,fdirection); +} +/*==========================================================*/ +void VelocityBCAdapter::adaptBC( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time ) +{ + this->setNodeVelocity(interactor,bc,worldX1,worldX2,worldX3,time); + bc->setBcAlgorithmType(algorithmType); +} +/*==========================================================*/ +void VelocityBCAdapter::setNodeVelocity( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep) +{ + //Geschwindigkeiten setzen + try + { + //PunktKoordinaten bestimmen + this->x1 = worldX1; + this->x2 = worldX2; + this->x3 = worldX3; + this->timeStep = timestep; + + if(tmpVx1Function) bc->setBoundaryVelocityX1((LBMReal)tmpVx1Function->Eval()); + if(tmpVx2Function) bc->setBoundaryVelocityX2((LBMReal)tmpVx2Function->Eval()); + if(tmpVx3Function) bc->setBoundaryVelocityX3((LBMReal)tmpVx3Function->Eval()); + } + catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")" + <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); } + catch(...) { throw UbException(UB_EXARGS,"unknown exception" ); } +} +/*==========================================================*/ +UbTupleDouble3 VelocityBCAdapter::getVelocity(const double& x1, const double& x2, const double& x3, const double& timeStep) const +{ + double vx1 = 0.0; + double vx2 = 0.0; + double vx3 = 0.0; + this->x1 = x1; + this->x2 = x2; + this->x3 = x3; + this->timeStep = timeStep; + + if(tmpVx1Function) vx1 = tmpVx1Function->Eval(); + if(tmpVx2Function) vx2 = tmpVx2Function->Eval(); + if(tmpVx3Function) vx3 = tmpVx3Function->Eval(); + + return UbTupleDouble3(vx1,vx2,vx3); +} +/*==========================================================*/ +string VelocityBCAdapter::toString() +{ + stringstream info; + info<<"D3Q27VelocityBCAdapter:\n"; + info<<" #vx1-functions = "<<(int)vx1BCs.size()<<endl; + info<<" #vx2-functions = "<<(int)vx2BCs.size()<<endl; + info<<" #vx3-functions = "<<(int)vx3BCs.size()<<endl; + info<<" protected variables: x1, x2, x3, t"<<endl; + + const vector<BCFunction>* bcvecs[3] = { &vx1BCs, &vx2BCs, &vx3BCs }; + for(int i=0; i<3; i++) + { + for(size_t pos=0; pos<bcvecs[i]->size(); ++pos) + { + info<<"\n vx"<<(i+1)<<"-function nr."<<pos<<":"<<endl; + info<<(*bcvecs[i])[pos]<<endl; + } + } + return info.str(); +} + + diff --git a/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.h b/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.h new file mode 100644 index 0000000000000000000000000000000000000000..1ed2bdde1ed401c5e9ae2ee6a31832f89a047414 --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/VelocityBCAdapter.h @@ -0,0 +1,162 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VelocityBCAdapter.h +//! \ingroup BoundarConditions +//! \author Sören Freudiger +//======================================================================================= +#ifndef VelocityBCAdapter_H +#define VelocityBCAdapter_H + +#include <iostream> +#include <string> +#include <sstream> +#include <vector> + +#include <basics/utilities/UbInfinity.h> + +#include <BCAdapter.h> +#include <BCFunction.h> + +//! \brief A class provides an interface for velocity boundary condition in grid generator. + +//! \details +//! Example: +//! \code{.cpp} vector<BCFunction> vx1BCs,vx2BCs,vx3BCs; +//! vx1BCs.push_back(BCFunction(0.01 , 0 , 100) ); //t=[0 ..100[ -> vx1 = 0.01 +//! vx1BCs.push_back(BCFunction(0.004, 100, 200) ); //t=[100..200[ -> vx1 = 0.004 +//! vx1BCs.push_back(BCFunction(0.03 , 200, 400) ); //t=[200..400] -> vx1 = 0.03 +//! +//! vx2BCs.push_back(BCFunction(0.02 , 0 , 200) ); //t=[0 ..200[ -> vx2 = 0.02 +//! vx2BCs.push_back(BCFunction(0.002, 200, 300) ); //t=[200..300[ -> vx2 = 0.002 +//! vx2BCs.push_back(BCFunction(0.043, 300, 600) ); //t=[300..600] -> vx2 = 0.043 +//! +//! VelocityBCAdapter bcAdapter(vx1BCs,vx2BCs,vx3BCs); +//! bcAdapter.setTimePeriodic(); //-> t=[0 ..100[ -> vx1 = 0.01 +//! // t=[100..200[ -> vx1 = 0.004 +//! // t=[200..400[ -> vx1 = 0.03 +//! // t=[400..500[ -> vx1 = 0.01 +//! // t=[500..600[ -> vx1 = 0.004 +//! // t=[600..800[ -> vx1 = 0.03 ... +//! // t=[0 ..200[ -> vx2 = 0.02 +//! // t=[200..300[ -> vx2 = 0.002 +//! // t=[300..600] -> vx2 = 0.043 +//! // t=[600..800[ -> vx2 = 0.02 +//! // t=[800..900[ -> vx2 = 0.002 +//! // t=[900..1200]-> vx2 = 0.043 ... +//! \endcode +//! Example of parabolic inflow: +//! \code{.cpp} +//! mu::Parser fct; +//! fct.SetExpr("max(vmax*(1.0-4.0*((x2-x2_vmax)^2+(x3-x3_vmax)^2)/H^2),0.0)"); //paraboloid (with vmax for (0/x2_vmax/x3_vmax) +//! fct.DefineConst("x2Vmax", 0.0 ); //x2-Pos für vmax +//! fct.DefineConst("x3Vmax", 0.0 ); //x3-Pos für vmax +//! fct.DefineConst("H" , diameterOfPipe); +//! fct.DefineConst("vmax" , vmax ); +//! VelocityBCAdapter velBC(true, false ,false ,fct, 0, BCFunction::INFCONST); +//! \endcode + +class VelocityBCAdapter : public BCAdapter +{ +public: + //constructors + VelocityBCAdapter() { this->init(); } + + VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const BCFunction& velVxBC ); + + VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function, const double& startTime, const double& endTime ); + + VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function1, const mu::Parser& function2, const mu::Parser& function3, const double& startTime, const double& endTime ); + + VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const std::string& functionstring, const double& startTime, const double& endTime ); + + VelocityBCAdapter(const BCFunction& velBC, bool x1Dir, bool x2Dir, bool x3Dir); + + VelocityBCAdapter(const BCFunction& velVx1BC, const BCFunction& velVx2BC, const BCFunction& velVx3BC); + + VelocityBCAdapter(const std::vector< BCFunction >& velVx1BCs, const std::vector< BCFunction >& velVx2BCs, const std::vector< BCFunction >& velVx3BCs); + + VelocityBCAdapter(const double& vx1, const double& vx1StartTime, const double& vx1EndTime, + const double& vx2, const double& vx2StartTime, const double& vx2EndTime, + const double& vx3, const double& vx3StartTime, const double& vx3EndTime); + + VelocityBCAdapter(const std::string& vx1Function, const double& vx1StartTime, const double& vx1EndTime, + const std::string& vx2Function, const double& vx2StartTime, const double& vx2EndTime, + const std::string& vx3Function, const double& vx3StartTime, const double& vx3EndTime ); + + //methods + void setTimePeriodic() { (this->type |= TIMEPERIODIC); } + void unsetTimePeriodic() { (this->type &= ~TIMEPERIODIC); } + bool isTimePeriodic() { return ((this->type & TIMEPERIODIC) == TIMEPERIODIC); } + + //The following is meant for moving objects... + void setNewVelocities(const double& vx1, const double& vx1StartTime, const double& vx1EndTime, + const double& vx2, const double& vx2StartTime, const double& vx2EndTime, + const double& vx3, const double& vx3StartTime, const double& vx3EndTime); + + + //------------- implements BCAdapter ----- start + std::string toString(); + + void init(const D3Q27Interactor* const& interactor, const double& time=0); + void update(const D3Q27Interactor* const& interactor, const double& time=0); + + void adaptBCForDirection( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 ); + void adaptBC( const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 ); + + //------------- implements BCAdapter ----- end + + UbTupleDouble3 getVelocity(const double& x1, const double& x2, const double& x3, const double& timeStep) const; + + +protected: + void init(); + void init(std::vector<BCFunction>& vxBCs); + + //time dependency is determined automatically via BCFunction intervals! + void setTimeDependent() { (this->type |= TIMEDEPENDENT); } + void unsetTimeDependent() { (this->type &= ~TIMEDEPENDENT); } + + void clear() { vx1BCs.clear(); vx2BCs.clear(); vx3BCs.clear(); this->init(); } + void setNodeVelocity(const D3Q27Interactor& interactor, SPtr<BoundaryConditions> bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep); + +private: + mutable mu::value_type x1, x2, x3; + mutable mu::value_type timeStep; + + mu::Parser* tmpVx1Function; + mu::Parser* tmpVx2Function; + mu::Parser* tmpVx3Function; + + std::vector<BCFunction> vx1BCs; + std::vector<BCFunction> vx2BCs; + std::vector<BCFunction> vx3BCs; + +}; + +#endif diff --git a/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.cpp b/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d61840a7ecb8307b62b37013e2aded7998a5234a --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.cpp @@ -0,0 +1,83 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VelocityBCAlgorithm.cpp +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#include "VelocityBCAlgorithm.h" +#include "DistributionArray3D.h" +#include "BoundaryConditions.h" + +VelocityBCAlgorithm::VelocityBCAlgorithm() +{ + BCAlgorithm::type = BCAlgorithm::VelocityBCAlgorithm; + BCAlgorithm::preCollision = false; +} +////////////////////////////////////////////////////////////////////////// +VelocityBCAlgorithm::~VelocityBCAlgorithm() +{ +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCAlgorithm> VelocityBCAlgorithm::clone() +{ + SPtr<BCAlgorithm> bc(new VelocityBCAlgorithm()); + return bc; +} +////////////////////////////////////////////////////////////////////////// +void VelocityBCAlgorithm::addDistributions(SPtr<DistributionArray3D> distributions) +{ + this->distributions = distributions; +} +////////////////////////////////////////////////////////////////////////// +void VelocityBCAlgorithm::applyBC() +{ + LBMReal f[D3Q27System::ENDF+1]; + LBMReal feq[D3Q27System::ENDF+1]; + distributions->getDistributionInv(f, x1, x2, x3); + LBMReal rho, vx1, vx2, vx3, drho; + calcMacrosFct(f, drho, vx1, vx2, vx3); + calcFeqFct(feq, drho, vx1, vx2, vx3); + + rho = 1.0+drho*compressibleFactor; + + for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) + { + if (bcPtr->hasVelocityBoundaryFlag(fdir)) + { + const int invDir = D3Q27System::INVDIR[fdir]; + LBMReal q = bcPtr->getQ(invDir); + LBMReal velocity = bcPtr->getBoundaryVelocity(invDir); + LBMReal fReturn = f[invDir] - velocity; + distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir); + } + } + +} + diff --git a/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.h b/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..03b33779e50489a45b6b5f597716ca0dbc0b2bfb --- /dev/null +++ b/VirtualFluidsCore/BoundaryConditions/VelocityBCAlgorithm.h @@ -0,0 +1,54 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VelocityBCAlgorithm.h +//! \ingroup BoundarConditions +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef VelocityBCAlgorithm_H +#define VelocityBCAlgorithm_H + +#include "BCAlgorithm.h" +#include <PointerDefinitions.h> + +class DistributionArray3D; + +//! \brief A class implements velocyty boundary condition +class VelocityBCAlgorithm : public BCAlgorithm +{ +public: + VelocityBCAlgorithm(); + ~VelocityBCAlgorithm(); + SPtr<BCAlgorithm> clone(); + void addDistributions(SPtr<DistributionArray3D> distributions); + void applyBC() override; +}; + +#endif + diff --git a/VirtualFluidsCore/CMakeLists.txt b/VirtualFluidsCore/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..041ad5363017623609cdbb1c4aa0fe7bd2d9d886 --- /dev/null +++ b/VirtualFluidsCore/CMakeLists.txt @@ -0,0 +1,46 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +######################################################## +## C++ PROJECT ### +######################################################## +PROJECT(VirtualFluids) + +################################################################# +### PACKAGES ### +################################################################# +SET(WITH_SUBFOLDERS_FOR_SG TRUE) + +INCLUDE(${SOURCE_ROOT}/ThirdParty/MuParser/CMakePackage.txt) + +#new VirtualFluids +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/BoundaryConditions/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Connectors/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Data/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Interactors/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/LBM/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Parallel/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Grid/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Visitors/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/CoProcessors/CMakePackage.txt) +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Utilities/CMakePackage.txt) + +#old VirtualFluids +INCLUDE(${SOURCE_ROOT}/VirtualFluidsBasics/VirtualFluidsBasics.cmake) + +INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/IncludsList.cmake) + +IF(${USE_GCC}) + SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} rt) + SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} gomp) +ENDIF() + +IF(${USE_INTEL}) + SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} irc) + SET(CAB_ADDITIONAL_LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS} parallel) +ENDIF() + +message("CAB_ADDITIONAL_LINK_LIBRARIES: " ${CAB_ADDITIONAL_LINK_LIBRARIES}) +################################################################# +### CREATE PROJECT ### +################################################################# +CREATE_CAB_PROJECT(VirtualFluids STATIC) diff --git a/VirtualFluidsCore/CoProcessors/CMakePackage.txt b/VirtualFluidsCore/CoProcessors/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/CoProcessors/CoProcessor.cpp b/VirtualFluidsCore/CoProcessors/CoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7ea981940d5a903aa7599a5bd104f891d26569d --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/CoProcessor.cpp @@ -0,0 +1,52 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CoProcessor.cpp +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "CoProcessor.h" + +#include "Grid3D.h" +#include "UbScheduler.h" + +CoProcessor::CoProcessor() +{ +} + +CoProcessor::CoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s): grid(grid), scheduler(s) +{ + +} + +CoProcessor::~CoProcessor() +{ + +} + diff --git a/VirtualFluidsCore/CoProcessors/CoProcessor.h b/VirtualFluidsCore/CoProcessors/CoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..31779a0f6b169a57b88e1d77140ddb181137e8a7 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/CoProcessor.h @@ -0,0 +1,66 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CoProcessor.h +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef CoProcessor_H +#define CoProcessor_H + +#include <PointerDefinitions.h> + +class Grid3D; +class UbScheduler; + +//! \class CoProcessor +//! \brief An abstract class implements observer design pettern +class CoProcessor +{ +public: + //! Class default constructor + CoProcessor(); + //! \brief Construct CoProcessor object for grid object and scheduler object. + //! \pre The Grid3D and UbScheduler objects must exist. + //! \param grid is observable Grid3D object + //! \param s is UbScheduler object for scheduling of observer + //! \details + //! Class CoProcessor implements the observer design pettern. CoProcessor object is observer. Grid3D object is observable. + CoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s); + //! Class destructor + virtual ~CoProcessor(); + //! \brief Updates observer + //! \param step is the actual time step + virtual void process(double step) = 0; +protected: + SPtr<Grid3D> grid; + SPtr<UbScheduler> scheduler; +}; +#endif + diff --git a/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp b/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38b11dd0119fabec07fd883c5240be643b2481e7 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp @@ -0,0 +1,94 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NUPSCounterCoProcessor.cpp +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "NUPSCounterCoProcessor.h" + +#include "Communicator.h" +#include "UbScheduler.h" +#include "Grid3D.h" + +NUPSCounterCoProcessor::NUPSCounterCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, int numOfThreads, SPtr<Communicator> comm) + : CoProcessor(grid, s), + numOfThreads(numOfThreads), + comm(comm), + nup(0), + nup_t(0), + nupsStep(0.0) +{ + if (comm->getProcessID() == comm->getRoot()) + { + timer.resetAndStart(); + + double nop = comm->getNumberOfProcesses(); + int minInitLevel = grid->getCoarsestInitializedLevel(); + int maxInitLevel = grid->getFinestInitializedLevel(); + UbTupleInt3 blocknx = grid->getBlockNX(); + double nod = (double)(val<1>(blocknx)) * (double)(val<2>(blocknx)) * (double)(val<3>(blocknx)); + nup = 0; + + for(int level = minInitLevel; level<=maxInitLevel; level++) + { + int nob = grid->getNumberOfBlocks(level); + nup_t += (double)(1<<level) * nob * nod; + } + nup = nup_t / nop; + } +} +////////////////////////////////////////////////////////////////////////// +NUPSCounterCoProcessor::~NUPSCounterCoProcessor() +{ +} +////////////////////////////////////////////////////////////////////////// +void NUPSCounterCoProcessor::process(double step) +{ + if(scheduler->isDue(step) ) + collectData(step); +} +////////////////////////////////////////////////////////////////////////// +void NUPSCounterCoProcessor::collectData(double step) +{ + if (comm->getProcessID() == comm->getRoot()) + { + double time = timer.stop(); + double nups_t = nup_t*(step-nupsStep)/time; + double nups = nup*(step-nupsStep)/time; + double tnups = nups/(double)numOfThreads; + UBLOG(logINFO, "Calculation step = "<<step); + UBLOG(logINFO, "Total performance = "<<nups_t<<" NUPS"); + UBLOG(logINFO, "Performance per process = "<<nups<<" NUPS"); + UBLOG(logINFO, "Performance per thread = "<<tnups<<" NUPS"); + UBLOG(logINFO, "Time for " << step-nupsStep <<" steps = "<< time <<" s"); + nupsStep = step; + timer.resetAndStart(); + } +} diff --git a/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h b/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..a398f10e9e8085a06757dbe243b2e6ad059491e1 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h @@ -0,0 +1,77 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NUPSCounterCoProcessor.h +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef NUPSCOUNTERCoProcessor_H_ +#define NUPSCOUNTERCoProcessor_H_ + +#include <PointerDefinitions.h> + +#include "CoProcessor.h" +#include "basics/utilities/UbTiming.h" + +class Communicator; +class Grid3D; +class UbScheduler; + +//! \class NUPSCounterCoProcessor +//! \brief A class calculates Nodal Updates Per Second (NUPS) +class NUPSCounterCoProcessor: public CoProcessor +{ +public: + //! \brief Construct NUPSCounterCoProcessor object for grid object and scheduler object. + //! \pre The Grid3D and UbScheduler objects must exist. + //! \param grid is observable Grid3D object + //! \param s is UbScheduler object for scheduling of observer + //! \param numOfThreads is number of threads + //! \param comm is Communicator object + NUPSCounterCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, int numOfThreads, SPtr<Communicator> comm); + virtual ~NUPSCounterCoProcessor(); + + void process(double step)override; + +protected: + //! Collect data for calculation of NUPS + //! \param step is a time step + void collectData(double step); + UbTimer timer; + int numOfThreads; + double numberOfNodes; + double numberOfBlocks; + double nup; + double nup_t; + double nupsStep; + SPtr<Communicator> comm; +}; + + +#endif diff --git a/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp b/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8256d2fea2c44b9f06df232c529212a49db61e98 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp @@ -0,0 +1,186 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteBlocksCoProcessor.cpp +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "WriteBlocksCoProcessor.h" +#include "basics/writer/WbWriterVtkXmlASCII.h" + +#include "D3Q27System.h" +#include "Block3D.h" +#include "UbScheduler.h" +#include "Communicator.h" +#include "Grid3D.h" + +WriteBlocksCoProcessor::WriteBlocksCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, + const std::string& path, WbWriter* const writer, + SPtr<Communicator> comm) : + CoProcessor(grid, s), + path(path), + writer(writer), + comm(comm) +{ + +} +////////////////////////////////////////////////////////////////////////// +WriteBlocksCoProcessor::~WriteBlocksCoProcessor() +{ +} +////////////////////////////////////////////////////////////////////////// +void WriteBlocksCoProcessor::process(double step) +{ + if(scheduler->isDue(step) ) + collectData(step); +} +////////////////////////////////////////////////////////////////////////// +void WriteBlocksCoProcessor::collectData(double step) +{ + if (comm->getProcessID() == comm->getRoot()) + { + int istep = int(step); + std::vector<std::string> filenames; + std::vector< UbTupleFloat3 > nodes; + std::vector< UbTupleInt8 > cells; + std::vector<std::string> celldatanames; + + celldatanames.push_back("isActive"); + celldatanames.push_back("rank"); + celldatanames.push_back("interface"); + celldatanames.push_back("ID"); + celldatanames.push_back("part"); + celldatanames.push_back("level"); + //celldatanames.push_back("connectorCF"); + //celldatanames.push_back("connectorFC"); +#if defined VF_FETOL + celldatanames.push_back("bundle"); +#endif + + std::vector< std::vector< double > > celldata(celldatanames.size()); + + int nr=0; + int minInitLevel = this->grid->getCoarsestInitializedLevel(); + int maxInitLevel = this->grid->getFinestInitializedLevel(); + + for(int level = minInitLevel; level<=maxInitLevel;level++) + { + std::vector<SPtr<Block3D>> blockVector; + grid->getBlocks(level, blockVector); + for(SPtr<Block3D> block : blockVector) + { + UbTupleDouble3 org = grid->getBlockWorldCoordinates(block); + UbTupleDouble3 blockLength = grid->getBlockLengths(block); + + nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)), (float)(val<3>(org)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)), (float)(val<3>(org)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)), (float)(val<3>(org)+val<3>(blockLength)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)), (float)(val<3>(org)+val<3>(blockLength)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)+val<3>(blockLength)))); + nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)+val<3>(blockLength)))); + cells.push_back(makeUbTuple(nr, nr+1, nr+2, nr+3, nr+4, nr+5, nr+6, nr+7)); + nr += 8; + + //data + celldata[0].push_back((double)block->isActive()); + celldata[1].push_back((double)block->getRank()); + celldata[2].push_back((double)block->hasInterpolationFlag()); + celldata[3].push_back((double)block->getGlobalID()); + celldata[4].push_back((double)block->getPart()); + celldata[5].push_back((double)block->getLevel()); + + //bool flag = false; + //std::vector<SPtr<Block3DConnector>> connectors; + + //block->pushBackLocalInterpolationConnectorsCF(connectors); + //for (std::size_t i = 0; i<connectors.size(); i++) + // if (connectors[i]) + // { + // if (connectors[i]->getSendDir() == D3Q27System::BS) + // { + + // flag = true; + // } + // } + + //if (flag) + //{ + // celldata[6].push_back(1); + // UBLOG(logINFO, "CF: "+block->toString()); + //} + //else + //{ + // celldata[6].push_back(0); + //} + + //flag = false; + //connectors.resize(0); + //block->pushBackLocalInterpolationConnectorsFC(connectors); + //for (std::size_t i = 0; i<connectors.size(); i++) + // if (connectors[i]) + // { + // if (connectors[i]->getSendDir() == D3Q27System::BS) + // { + + // flag = true; + // } + // } + + //if (flag) + //{ + // celldata[7].push_back(1); + // UBLOG(logINFO, "FC: "+block->toString()); + //} + //else + //{ + // celldata[7].push_back(0); + //} + +#ifdef VF_FETOL + celldata[6].push_back( (double)block->getBundle()); +#endif + } + } + + filenames.push_back(writer->writeOctsWithCellData(path+"/blocks/blocks_" + UbSystem::toString(grid->getRank()) + "_" + UbSystem::toString(istep),nodes,cells,celldatanames,celldata)); + + if (istep == CoProcessor::scheduler->getMinBegin()) + { + WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"/blocks/blocks_collection",filenames,istep,false); + } + else + { + WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path + "/blocks/blocks_collection", filenames, istep, false); + } + + UBLOG(logINFO,"WriteBlocksCoProcessor step: " << istep); + } +} diff --git a/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h b/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..d797dbcccfb9b0e56c123e228c1c464411d4cde1 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h @@ -0,0 +1,75 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteBlocksCoProcessor.h +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef WriteBlocksCoProcessor_H_ +#define WriteBlocksCoProcessor_H_ + +#include <PointerDefinitions.h> +#include <string> + +#include "CoProcessor.h" + +class Communicator; +class Grid3D; +class UbScheduler; +class WbWriter; + +//! \class WriteBlocksCoProcessor +//! \brief A class writes a block grid to a VTK-file +class WriteBlocksCoProcessor: public CoProcessor +{ +public: + //! \brief Construct WriteBlocksCoProcessor object. + //! \pre The Grid3D and UbScheduler objects must exist. + //! \param grid is observable Grid3D object + //! \param s is UbScheduler object for scheduling of observer + //! \param path is path of folder for output + //! \param writer is WbWriter object + //! \param comm is Communicator object + WriteBlocksCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string& path, WbWriter* const writer, SPtr<Communicator> comm); + virtual ~WriteBlocksCoProcessor(); + + void process(double step) override; + +protected: + //! Collect data for VTK-file + //! \param step is a time step + void collectData(double step); + + std::string path; + WbWriter* writer; + SPtr<Communicator> comm; +}; + + +#endif diff --git a/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp b/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc6601c732c8c1a69677c7a574e7b53831bb6b47 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp @@ -0,0 +1,299 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteBoundaryConditionsCoProcessor.cpp +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "WriteBoundaryConditionsCoProcessor.h" +#include "LBMKernel.h" +#include "BCProcessor.h" +#include <vector> +#include <string> + +#include "basics/writer/WbWriterVtkXmlASCII.h" +#include "Grid3D.h" +#include "Block3D.h" +#include "LBMUnitConverter.h" +#include "Communicator.h" +#include "WbWriter.h" +#include "UbScheduler.h" +#include "CbArray3D.h" +#include "BCArray3D.h" + +using namespace std; + +WriteBoundaryConditionsCoProcessor::WriteBoundaryConditionsCoProcessor() +{ + +} +////////////////////////////////////////////////////////////////////////// +WriteBoundaryConditionsCoProcessor::WriteBoundaryConditionsCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, + const std::string& path, WbWriter* const writer, SPtr<Communicator> comm) + : CoProcessor(grid, s), + path(path), + writer(writer), + comm(comm) +{ + gridRank = comm->getProcessID(); + minInitLevel = this->grid->getCoarsestInitializedLevel(); + maxInitLevel = this->grid->getFinestInitializedLevel(); + + blockVector.resize(maxInitLevel+1); + + for (int level = minInitLevel; level<=maxInitLevel; level++) + { + grid->getBlocks(level, gridRank, true, blockVector[level]); + } +} +////////////////////////////////////////////////////////////////////////// +void WriteBoundaryConditionsCoProcessor::process(double step) +{ + if (scheduler->isDue(step)) + collectData(step); + + UBLOG(logDEBUG3, "WriteBoundaryConditionsCoProcessor::update:"<<step); +} +////////////////////////////////////////////////////////////////////////// +void WriteBoundaryConditionsCoProcessor::collectData(double step) +{ + int istep = static_cast<int>(step); + + for (int level = minInitLevel; level<=maxInitLevel; level++) + { + for(SPtr<Block3D> block : blockVector[level]) + { + if (block) + { + addDataGeo(block); + } + } + } + + string pfilePath, partPath, subfolder, cfilePath; + + subfolder = "bc"+UbSystem::toString(istep); + pfilePath = path+"/bc/"+subfolder; + cfilePath = path+"/bc/bc_collection"; + partPath = pfilePath+"/bc"+UbSystem::toString(gridRank)+"_"+UbSystem::toString(istep); + + + string partName = writer->writeOctsWithNodeData(partPath, nodes, cells, datanames, data); + size_t found = partName.find_last_of("/"); + string piece = partName.substr(found+1); + piece = subfolder+"/"+piece; + + vector<string> cellDataNames; + vector<std::string> pieces; + pieces.push_back(piece); + if (comm->getProcessID()==comm->getRoot()) + { + string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath, pieces, datanames, cellDataNames); + found = pname.find_last_of("/"); + piece = pname.substr(found+1); + + vector<string> filenames; + filenames.push_back(piece); + if (step==CoProcessor::scheduler->getMinBegin()) + { + WbWriterVtkXmlASCII::getInstance()->writeCollection(cfilePath, filenames, istep, false); + } + else + { + WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath, filenames, istep, false); + } + UBLOG(logINFO, "WriteBoundaryConditionsCoProcessor step: "<<istep); + } + + clearData(); +} +////////////////////////////////////////////////////////////////////////// +void WriteBoundaryConditionsCoProcessor::clearData() +{ + nodes.clear(); + cells.clear(); + datanames.clear(); + data.clear(); +} +////////////////////////////////////////////////////////////////////////// +void WriteBoundaryConditionsCoProcessor::addDataGeo(SPtr<Block3D> block) +{ + UbTupleDouble3 org = grid->getBlockWorldCoordinates(block); + UbTupleDouble3 blockLengths = grid->getBlockLengths(block); + UbTupleDouble3 nodeOffset = grid->getNodeOffset(block); + double dx = grid->getDeltaX(block); + + double level = (double)block->getLevel(); + + //Diese Daten werden geschrieben: + datanames.resize(0); + datanames.push_back("Boundary Conditions"); + datanames.push_back("Geometry"); + datanames.push_back("Level"); + datanames.push_back("Algorithm"); + //datanames.push_back("Interface CF"); + datanames.push_back("qs"); + + data.resize(datanames.size()); + + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + + //knotennummerierung faengt immer bei 0 an! + int SWB, SEB, NEB, NWB, SWT, SET, NET, NWT; + + int minX1 = 0; + int minX2 = 0; + int minX3 = 0; + + int maxX1 = (int)bcArray->getNX1(); + int maxX2 = (int)bcArray->getNX2(); + int maxX3 = (int)bcArray->getNX3(); + + //nummern vergeben und node vector erstellen + daten sammeln + CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3, -1); + //D3Q27BoundaryConditionPtr bcPtr; + int nr = (int)nodes.size(); + + maxX1 -= 1; + maxX2 -= 1; + maxX3 -= 1; + + int s=0; + + + + for (size_t ix3 = minX3; ix3<=maxX3; ix3++) + { + for (size_t ix2 = minX2; ix2<=maxX2; ix2++) + { + for (size_t ix1 = minX1; ix1<=maxX1; ix1++) + { + if (!bcArray->isUndefined(ix1, ix2, ix3)) + { + int index = 0; + nodeNumbers(ix1, ix2, ix3) = nr++; + nodes.push_back(makeUbTuple(float(val<1>(org)-val<1>(nodeOffset)+ix1*dx), + float(val<2>(org)-val<2>(nodeOffset)+ix2*dx), + float(val<3>(org)-val<3>(nodeOffset)+ix3*dx))); + + + + if (!bcArray->hasBC(ix1, ix2, ix3)) + { + data[index++].push_back(0.0); + } + else if (bcArray->getBC(ix1, ix2, ix3)->hasNoSlipBoundary()) + data[index++].push_back(1.0); + else if (bcArray->getBC(ix1, ix2, ix3)->hasVelocityBoundary()) + data[index++].push_back(2.0); + else if (bcArray->getBC(ix1, ix2, ix3)->hasDensityBoundary()) + data[index++].push_back(3.0); + else if (bcArray->getBC(ix1, ix2, ix3)->hasSlipBoundary()) + data[index++].push_back(4.0); + //else + // data[0].push_back(5.0); + + + if (bcArray->isSolid(ix1, ix2, ix3)) + { + data[index++].push_back(1.0); + } + else + { + data[index++].push_back(0.0); + } + + + data[index++].push_back(level); + + if (bcArray->hasBC(ix1, ix2, ix3)) + data[index++].push_back(bcArray->getBC(ix1, ix2, ix3)->getBcAlgorithmType()); + else + data[index++].push_back(-1.0); + + //if (bcArray->isInterfaceCF(ix1, ix2, ix3)) + //{ + // data[3].push_back(1.0); + //} + //else + //{ + // data[3].push_back(0.0); + //} + + if (bcArray->hasBC(ix1, ix2, ix3)) + { + unsigned int a = 1; + unsigned int b = 0; + for (int fdir = D3Q27System::FSTARTDIR; fdir <= D3Q27System::FENDDIR; fdir++) + { + if (bcArray->getBC(ix1, ix2, ix3)->hasVelocityBoundaryFlag(fdir)) + { + a = a << 1; + if (bcArray->getBC(ix1, ix2, ix3)->hasVelocityBoundaryFlag(fdir)) + { + b = b | a; + } + } + } + data[index++].push_back(b); + } + else + data[index++].push_back(-1.0); + } + } + } + } + + maxX1 -= 1; + maxX2 -= 1; + maxX3 -= 1; + + //cell vector erstellen + for (int ix3 = minX3; ix3<=maxX3; ix3++) + { + for (int ix2 = minX2; ix2<=maxX2; ix2++) + { + for (int ix1 = minX1; ix1<=maxX1; ix1++) + { + if ((SWB = nodeNumbers(ix1, ix2, ix3))>=0 + &&(SEB = nodeNumbers(ix1+1, ix2, ix3))>=0 + &&(NEB = nodeNumbers(ix1+1, ix2+1, ix3))>=0 + &&(NWB = nodeNumbers(ix1, ix2+1, ix3))>=0 + &&(SWT = nodeNumbers(ix1, ix2, ix3+1))>=0 + &&(SET = nodeNumbers(ix1+1, ix2, ix3+1))>=0 + &&(NET = nodeNumbers(ix1+1, ix2+1, ix3+1))>=0 + &&(NWT = nodeNumbers(ix1, ix2+1, ix3+1))>=0) + { + cells.push_back(makeUbTuple(SWB, SEB, NEB, NWB, SWT, SET, NET, NWT)); + } + } + } + } +} diff --git a/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h b/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..2c2a2f612236913c50174ee390ae2c3b6da1f6d5 --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h @@ -0,0 +1,89 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteBoundaryConditionsCoProcessor.h +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef WriteBoundaryConditionsCoProcessor_H +#define WriteBoundaryConditionsCoProcessor_H + +#include <PointerDefinitions.h> +#include <string> +#include <vector> + +#include "CoProcessor.h" +#include "UbTuple.h" + +class Communicator; +class Grid3D; +class UbScheduler; +class WbWriter; +class Block3D; +class LBMUnitConverter; + +//! \brief A class writes boundary conditions information to a VTK-file +class WriteBoundaryConditionsCoProcessor : public CoProcessor +{ +public: + WriteBoundaryConditionsCoProcessor(); + //! \brief Construct WriteBoundaryConditionsCoProcessor object + //! \pre The Grid3D and UbScheduler objects must exist + //! \param grid is observable Grid3D object + //! \param s is UbScheduler object for scheduling of observer + //! \param path is path of folder for output + //! \param writer is WbWriter object + //! \param comm is Communicator object + WriteBoundaryConditionsCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string& path, WbWriter* const writer, SPtr<Communicator> comm); + ~WriteBoundaryConditionsCoProcessor() {} + + void process(double step) override; + +protected: + //! Collect data for VTK-file + //! \param step is a time step + void collectData(double step); + void addDataGeo(SPtr<Block3D> block); + void clearData(); + +private: + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt8> cells; + std::vector<std::string> datanames; + std::vector<std::vector<double> > data; + std::string path; + WbWriter* writer; + bool bcInformation; + std::vector<std::vector<SPtr<Block3D> > > blockVector; + int minInitLevel; + int maxInitLevel; + int gridRank; + SPtr<Communicator> comm; +}; +#endif diff --git a/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp b/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7a3788850684f533960a7eebfb57ad1a6208efa --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp @@ -0,0 +1,266 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteMacroscopicQuantitiesCoProcessor.cpp +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "WriteMacroscopicQuantitiesCoProcessor.h" +#include "LBMKernel.h" +#include "BCProcessor.h" +#include <vector> +#include <string> + +#include "basics/writer/WbWriterVtkXmlASCII.h" +#include "DataSet3D.h" +#include "UbScheduler.h" +#include "Grid3D.h" +#include "Communicator.h" +#include "LBMUnitConverter.h" +#include "Block3D.h" +#include "BCArray3D.h" + +WriteMacroscopicQuantitiesCoProcessor::WriteMacroscopicQuantitiesCoProcessor() +{ + +} +////////////////////////////////////////////////////////////////////////// +WriteMacroscopicQuantitiesCoProcessor::WriteMacroscopicQuantitiesCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, + const std::string& path, WbWriter* const writer, + SPtr<LBMUnitConverter> conv, + SPtr<Communicator> comm) + : CoProcessor(grid, s), + path(path), + writer(writer), + conv(conv), + comm(comm) +{ + gridRank = comm->getProcessID(); + minInitLevel = this->grid->getCoarsestInitializedLevel(); + maxInitLevel = this->grid->getFinestInitializedLevel(); + + blockVector.resize(maxInitLevel+1); + + for (int level = minInitLevel; level<=maxInitLevel; level++) + { + grid->getBlocks(level, gridRank, true, blockVector[level]); + } +} +////////////////////////////////////////////////////////////////////////// +void WriteMacroscopicQuantitiesCoProcessor::init() +{ + +} +////////////////////////////////////////////////////////////////////////// +void WriteMacroscopicQuantitiesCoProcessor::process(double step) +{ + if(scheduler->isDue(step) ) + collectData(step); + + UBLOG(logDEBUG3, "WriteMacroscopicQuantitiesCoProcessor::update:" << step); +} +////////////////////////////////////////////////////////////////////////// +void WriteMacroscopicQuantitiesCoProcessor::collectData(double step) +{ + int istep = static_cast<int>(step); + + for(int level = minInitLevel; level<=maxInitLevel;level++) + { + for(SPtr<Block3D> block : blockVector[level]) + { + if (block) + { + addDataMQ(block); + } + } + } + + std::string pfilePath, partPath, subfolder, cfilePath; + + subfolder = "mq"+UbSystem::toString(istep); + pfilePath = path+"/mq/"+subfolder; + cfilePath = path+"/mq/mq_collection"; + partPath = pfilePath+"/mq"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep); + + + std::string partName = writer->writeOctsWithNodeData(partPath,nodes,cells,datanames,data); + size_t found=partName.find_last_of("/"); + std::string piece = partName.substr(found+1); + piece = subfolder + "/" + piece; + + std::vector<std::string> cellDataNames; + std::vector<std::string> pieces; + pieces.push_back(piece); + if (comm->getProcessID() == comm->getRoot()) + { + std::string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath,pieces,datanames,cellDataNames); + found=pname.find_last_of("/"); + piece = pname.substr(found+1); + + std::vector<std::string> filenames; + filenames.push_back(piece); + if (step == CoProcessor::scheduler->getMinBegin()) + { + WbWriterVtkXmlASCII::getInstance()->writeCollection(cfilePath,filenames,istep,false); + } + else + { + WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath,filenames,istep,false); + } + UBLOG(logINFO,"WriteMacroscopicQuantitiesCoProcessor step: " << istep); + } + + clearData(); +} +////////////////////////////////////////////////////////////////////////// +void WriteMacroscopicQuantitiesCoProcessor::clearData() +{ + nodes.clear(); + cells.clear(); + datanames.clear(); + data.clear(); +} +////////////////////////////////////////////////////////////////////////// +void WriteMacroscopicQuantitiesCoProcessor::addDataMQ(SPtr<Block3D> block) +{ + double blockID = (double)block->getGlobalID(); + + //This data is written: + datanames.resize(0); + datanames.push_back("DRho"); + datanames.push_back("Press"); + datanames.push_back("Vx"); + datanames.push_back("Vy"); + datanames.push_back("Vz"); + + data.resize(datanames.size()); + + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + SPtr<DistributionArray3D> distributions = kernel->getDataSet()->getFdistributions(); + LBMReal f[D3Q27System::ENDF+1]; + LBMReal vx1,vx2,vx3,drho,press; + + //node numbering always starts at 0! + int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT; + + if(block->getKernel()->getCompressible()) + { + calcMacros = &D3Q27System::calcCompMacroscopicValues; + } + else + { + calcMacros = &D3Q27System::calcIncompMacroscopicValues; + } + + int minX1 = 0; + int minX2 = 0; + int minX3 = 0; + + int maxX1 = (int)(distributions->getNX1()); + int maxX2 = (int)(distributions->getNX2()); + int maxX3 = (int)(distributions->getNX3()); + + //assign numbers and create node vector + collect data + CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1); + maxX1 -= 2; + maxX2 -= 2; + maxX3 -= 2; + + int nr = (int)nodes.size(); + + for(int ix3=minX3; ix3<=maxX3; ix3++) + { + for(int ix2=minX2; ix2<=maxX2; ix2++) + { + for(int ix1=minX1; ix1<=maxX1; ix1++) + { + if(!bcArray->isUndefined(ix1,ix2,ix3) && !bcArray->isSolid(ix1,ix2,ix3)) + { + int index = 0; + nodeNumbers(ix1,ix2,ix3) = nr++; + Vector3D worldCoordinates = grid->getNodeCoordinates(block, ix1, ix2, ix3); + nodes.push_back( UbTupleFloat3(float(worldCoordinates[0]), + float(worldCoordinates[1]), + float(worldCoordinates[2]) )); + + distributions->getDistribution(f, ix1, ix2, ix3); + calcMacros(f,drho,vx1,vx2,vx3); + press = D3Q27System::calcPress(f,drho,vx1,vx2,vx3); + + if (UbMath::isNaN(drho) || UbMath::isInfinity(drho)) + UB_THROW( UbException(UB_EXARGS,"drho is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+ + ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3))); + if (UbMath::isNaN(press) || UbMath::isInfinity(press)) + UB_THROW( UbException(UB_EXARGS,"press is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+ + ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3))); + if (UbMath::isNaN(vx1) || UbMath::isInfinity(vx1)) + UB_THROW( UbException(UB_EXARGS,"vx1 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+ + ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3))); + if (UbMath::isNaN(vx2) || UbMath::isInfinity(vx2)) + UB_THROW( UbException(UB_EXARGS,"vx2 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+ + ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3))); + if (UbMath::isNaN(vx3) || UbMath::isInfinity(vx3)) + UB_THROW( UbException(UB_EXARGS,"vx3 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+ + ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3))); + + data[index++].push_back(drho * conv->getFactorDensityLbToW()); + data[index++].push_back(press * conv->getFactorPressureLbToW()); + data[index++].push_back(vx1 * conv->getFactorVelocityLbToW()); + data[index++].push_back(vx2 * conv->getFactorVelocityLbToW()); + data[index++].push_back(vx3 * conv->getFactorVelocityLbToW()); + } + } + } + } + maxX1 -= 1; + maxX2 -= 1; + maxX3 -= 1; + //cell vector erstellen + for(int ix3=minX3; ix3<=maxX3; ix3++) + { + for(int ix2=minX2; ix2<=maxX2; ix2++) + { + for(int ix1=minX1; ix1<=maxX1; ix1++) + { + if( (SWB=nodeNumbers( ix1 , ix2, ix3 )) >= 0 + && (SEB=nodeNumbers( ix1+1, ix2, ix3 )) >= 0 + && (NEB=nodeNumbers( ix1+1, ix2+1, ix3 )) >= 0 + && (NWB=nodeNumbers( ix1 , ix2+1, ix3 )) >= 0 + && (SWT=nodeNumbers( ix1 , ix2, ix3+1 )) >= 0 + && (SET=nodeNumbers( ix1+1, ix2, ix3+1 )) >= 0 + && (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0 + && (NWT=nodeNumbers( ix1 , ix2+1, ix3+1 )) >= 0 ) + { + cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) ); + } + } + } + } +} diff --git a/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h b/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..76ecc9437b38078e596febd9c8747189d92b973e --- /dev/null +++ b/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h @@ -0,0 +1,102 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WriteMacroscopicQuantitiesCoProcessor.h +//! \ingroup CoProcessors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef WriteMacroscopicQuantitiesCoProcessor_H +#define WriteMacroscopicQuantitiesCoProcessor_H + +#include <PointerDefinitions.h> +#include <string> +#include <vector> + +#include "CoProcessor.h" +#include "UbTuple.h" +#include "LBMSystem.h" + +class Communicator; +class Grid3D; +class UbScheduler; +class LBMUnitConverter; +class WbWriter; +class Block3D; + + +//! \brief A class writes macroscopic quantities information to a VTK-file +class WriteMacroscopicQuantitiesCoProcessor : public CoProcessor +{ +public: + WriteMacroscopicQuantitiesCoProcessor(); + //! \brief Construct WriteMacroscopicQuantitiesCoProcessor object + //! \pre The Grid3D and UbScheduler objects must exist + //! \param grid is observable Grid3D object + //! \param s is UbScheduler object for scheduling of observer + //! \param path is path of folder for output + //! \param writer is WbWriter object + //! \param conv is LBMUnitConverter object + //! \param comm is Communicator object + WriteMacroscopicQuantitiesCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, + const std::string& path, WbWriter* const writer, + SPtr<LBMUnitConverter> conv, SPtr<Communicator> comm); + ~WriteMacroscopicQuantitiesCoProcessor(){} + + void process(double step) override; + +protected: + //! Collect data for VTK-file + //! \param step is a time step + void collectData(double step); + //! Collect data for VTK-file + //! \param block is a time step + void addDataMQ(SPtr<Block3D> block); + void clearData(); + +private: + void init(); + std::vector<UbTupleFloat3> nodes; + std::vector<UbTupleInt8> cells; + std::vector<std::string> datanames; + std::vector<std::vector<double> > data; + std::string path; + WbWriter* writer; + SPtr<LBMUnitConverter> conv; + bool bcInformation; + std::vector<std::vector<SPtr<Block3D> > > blockVector; + int minInitLevel; + int maxInitLevel; + int gridRank; + SPtr<Communicator> comm; + + typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/); + CalcMacrosFct calcMacros; +}; + +#endif diff --git a/VirtualFluidsCore/Connectors/Block3DConnector.h b/VirtualFluidsCore/Connectors/Block3DConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..2cf3cee9137d82598d9f7552bac0fbc1ea8dece7 --- /dev/null +++ b/VirtualFluidsCore/Connectors/Block3DConnector.h @@ -0,0 +1,82 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Block3DConnector.h +//! \ingroup Connectors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BLOCK2DCONNECTOR_H +#define BLOCK2DCONNECTOR_H + +#include <vector> +#include <string> + +#include <basics/utilities/UbTuple.h> + +#include <PointerDefinitions.h> + +//! \brief Abstract class of connectors +//! \details Connector send and receive full distributions between two blocks in shared memory. +class Block3DConnector +{ +public: + Block3DConnector() : sendDir(-1) {} + Block3DConnector(const int& sendDir) : sendDir(sendDir) {} + virtual ~Block3DConnector() {} + //!Iniitializes connector + virtual void init()=0; + //!Synchronizes the send-buffer length + virtual void sendTransmitterDataSize()=0; + //!Synchronizes the receive-buffer length + virtual void receiveTransmitterDataSize()=0; + + //Send (should be called in given order!!!) + virtual void prepareForSend()=0; + virtual void fillSendVectors()=0; + virtual void sendVectors()=0; + + //Receive (should be called in given order!!!) + virtual void prepareForReceive()=0; + virtual void receiveVectors()=0; + virtual void distributeReceiveVectors()=0; + + //info section + virtual bool isLocalConnector() = 0; + virtual bool isRemoteConnector() = 0; + virtual bool isInterpolationConnectorCF() = 0; + virtual bool isInterpolationConnectorFC() = 0; + + //grid refinement + virtual int getSendDir() const { return sendDir; } + +protected: + int sendDir; +}; + +#endif //BLOCK3DCONNECTOR_H diff --git a/VirtualFluidsCore/Connectors/CMakePackage.txt b/VirtualFluidsCore/Connectors/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..e3e3f9a387b022a62ecc0d63c3ef0210313e906d --- /dev/null +++ b/VirtualFluidsCore/Connectors/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) \ No newline at end of file diff --git a/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp b/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26802ce3f9fc7b574c8023b83c2f79072185cc51 --- /dev/null +++ b/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp @@ -0,0 +1,243 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27ETFullDirectConnector.cpp +//! \ingroup Connectors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "D3Q27ETFullDirectConnector.h" +#include "LBMKernel.h" +#include "D3Q27EsoTwist3DSplittedVector.h" +#include "DataSet3D.h" + +using namespace std; + +D3Q27ETFullDirectConnector::D3Q27ETFullDirectConnector(SPtr<Block3D> from, SPtr<Block3D> to, int sendDir) + : LocalBlock3DConnector(from, to, sendDir) + +{ + +} +////////////////////////////////////////////////////////////////////////// +void D3Q27ETFullDirectConnector::init() +{ + maxX1 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1() - 1; + maxX2 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2() - 1; + maxX3 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3() - 1; + + fFrom = dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions()); + fTo = dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions()); +} +////////////////////////////////////////////////////////////////////////// +void D3Q27ETFullDirectConnector::sendVectors() +{ + localDistributionsFrom = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getLocalDistributions(); + nonLocalDistributionsFrom = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getNonLocalDistributions(); + zeroDistributionsFrom = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getZeroDistributions(); + + localDistributionsTo = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getLocalDistributions(); + nonLocalDistributionsTo = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getNonLocalDistributions(); + zeroDistributionsTo = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getZeroDistributions(); + + //EAST + if (sendDir == D3Q27System::E) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(maxX1 - 1, x2, x3, 0, x2, x3); + } + } + } + //WEST + else if (sendDir == D3Q27System::W) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(1, x2, x3, maxX1, x2, x3); + } + } + } + //NORTH + else if (sendDir == D3Q27System::N) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, maxX2 - 1, x3, x1, 0, x3); + } + } + } + //SOUTH + else if (sendDir == D3Q27System::S) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, 1, x3, x1, maxX2, x3); + } + } + } + + //TOP + else if (sendDir == D3Q27System::T) + { + for (int x2 = 1; x2 < maxX2; x2++) + { + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, x2, maxX3 - 1, x1, x2, 0); + } + } + } + //BOTTOM + else if (sendDir == D3Q27System::B) + { + for (int x2 = 1; x2 < maxX2; x2++) + { + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, x2, 1, x1, x2, maxX3); + } + } + } + //NORTHEAST + else if (sendDir == D3Q27System::NE) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + exchangeData(maxX1 - 1, maxX2 - 1, x3, 0, 0, x3); + } + } + //NORTHWEST + else if (sendDir == D3Q27System::NW) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + exchangeData(1, maxX2 - 1, x3, maxX1, 0, x3); + } + } + //SOUTHWEST + else if (sendDir == D3Q27System::SW) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + exchangeData(1, 1, x3, maxX1, maxX2, x3); + } + } + //SOUTHEAST + else if (sendDir == D3Q27System::SE) + { + for (int x3 = 1; x3 < maxX3; x3++) + { + exchangeData(maxX1 - 1, 1, x3, 0, maxX2, x3); + } + } + else if (sendDir == D3Q27System::TE) + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(maxX1 - 1, x2, maxX3 - 1, 0, x2, 0); + } + else if (sendDir == D3Q27System::BW) + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(1, x2, 1, maxX1, x2, maxX3); + } + else if (sendDir == D3Q27System::BE) + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(maxX1 - 1, x2, 1, 0, x2, maxX3); + } + else if (sendDir == D3Q27System::TW) + for (int x2 = 1; x2 < maxX2; x2++) + { + exchangeData(1, x2, maxX3 - 1, maxX1, x2, 0); + } + else if (sendDir == D3Q27System::TN) + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, maxX2 - 1, maxX3 - 1, x1, 0, 0); + } + else if (sendDir == D3Q27System::BS) + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, 1, 1, x1, maxX2, maxX3); + } + else if (sendDir == D3Q27System::BN) + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, maxX2 - 1, 1, x1, 0, maxX3); + } + + else if (sendDir == D3Q27System::TS) + for (int x1 = 1; x1 < maxX1; x1++) + { + exchangeData(x1, 1, maxX3 - 1, x1, maxX2, 0); + } + + else if (sendDir == D3Q27System::TSW) + { + exchangeData(1, 1, maxX3 - 1, maxX1, maxX2, 0); + } + else if (sendDir == D3Q27System::TSE) + { + exchangeData(maxX1 - 1, 1, maxX3 - 1, 0, maxX2, 0); + } + else if (sendDir == D3Q27System::TNW) + { + exchangeData(1, maxX2 - 1, maxX3 - 1, maxX1, 0, 0); + } + else if (sendDir == D3Q27System::TNE) + { + exchangeData(maxX1 - 1, maxX2 - 1, maxX3 - 1, 0, 0, 0); + } + else if (sendDir == D3Q27System::BSW) + { + exchangeData(1, 1, 1, maxX1, maxX2, maxX3); + } + else if (sendDir == D3Q27System::BSE) + { + exchangeData(maxX1 - 1, 1, 1, 0, maxX2, maxX3); + } + else if (sendDir == D3Q27System::BNW) + { + exchangeData(1, maxX2 - 1, 1, maxX1, 0, maxX3); + } + else if (sendDir == D3Q27System::BNE) + { + exchangeData(maxX1 - 1, maxX2 - 1, 1, 0, 0, maxX3); + } + else UB_THROW(UbException(UB_EXARGS, "unknown dir")); +} + diff --git a/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h b/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..052ade1996c103f53b3d03e38525d90235f06c5f --- /dev/null +++ b/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h @@ -0,0 +1,107 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27ETFullDirectConnector.h +//! \ingroup Connectors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef D3Q27ETFULLDIRECTCONNECTOR_H +#define D3Q27ETFULLDIRECTCONNECTOR_H + +#include "LocalBlock3DConnector.h" +#include "Block3D.h" +#include "D3Q27System.h" +#include "basics/container/CbArray3D.h" +#include "basics/container/CbArray4D.h" +#include "EsoTwist3D.h" + +//! \brief Exchange data between blocks. +//! \details Connector send and receive full distributions between two blocks in shared memory. +class D3Q27ETFullDirectConnector : public LocalBlock3DConnector +{ +public: + D3Q27ETFullDirectConnector(SPtr<Block3D> from, SPtr<Block3D> to, int sendDir); + void init(); + void sendVectors(); + +protected: + inline void exchangeData(int x1From, int x2From, int x3From, int x1To, int x2To, int x3To); +private: + int maxX1; + int maxX2; + int maxX3; + + CbArray4D <LBMReal, IndexerX4X3X2X1>::CbArray4DPtr localDistributionsFrom; + CbArray4D <LBMReal, IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsFrom; + CbArray3D <LBMReal, IndexerX3X2X1>::CbArray3DPtr zeroDistributionsFrom; + + CbArray4D <LBMReal, IndexerX4X3X2X1>::CbArray4DPtr localDistributionsTo; + CbArray4D <LBMReal, IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsTo; + CbArray3D <LBMReal, IndexerX3X2X1>::CbArray3DPtr zeroDistributionsTo; + + SPtr<EsoTwist3D> fFrom; + SPtr<EsoTwist3D> fTo; +}; + + +////////////////////////////////////////////////////////////////////////// +inline void D3Q27ETFullDirectConnector::exchangeData(int x1From, int x2From, int x3From, int x1To, int x2To, int x3To) +{ + (*this->localDistributionsTo)(D3Q27System::ET_E, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_E, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_N, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_N, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_T, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_T, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_NE, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_NE, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_NW, x1To + 1, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_NW, x1From + 1, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TE, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TE, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TW, x1To + 1, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TW, x1From + 1, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TN, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TN, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TS, x1To, x2To + 1, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TS, x1From, x2From + 1, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TNE, x1To, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TNE, x1From, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TNW, x1To + 1, x2To, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TNW, x1From + 1, x2From, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TSE, x1To, x2To + 1, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TSE, x1From, x2From + 1, x3From); + (*this->localDistributionsTo)(D3Q27System::ET_TSW, x1To + 1, x2To + 1, x3To) = (*this->localDistributionsFrom)(D3Q27System::ET_TSW, x1From + 1, x2From + 1, x3From); + + (*this->nonLocalDistributionsTo)(D3Q27System::ET_W, x1To + 1, x2To, x3To) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_W, x1From + 1, x2From, x3From); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_S, x1To, x2To + 1, x3To) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_S, x1From, x2From + 1, x3From); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_B, x1To, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_B, x1From, x2From, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_SW, x1To + 1, x2To + 1, x3To) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SW, x1From + 1, x2From + 1, x3From); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_SE, x1To, x2To + 1, x3To) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SE, x1From, x2From + 1, x3From); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BW, x1To + 1, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BW, x1From + 1, x2From, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BE, x1To, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BE, x1From, x2From, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BS, x1To, x2To + 1, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BS, x1From, x2From + 1, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BN, x1To, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BN, x1From, x2From, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSW, x1To + 1, x2To + 1, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSW, x1From + 1, x2From + 1, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSE, x1To, x2To + 1, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSE, x1From, x2From + 1, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNW, x1To + 1, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNW, x1From + 1, x2From, x3From + 1); + (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNE, x1To, x2To, x3To + 1) = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNE, x1From, x2From, x3From + 1); + + (*this->zeroDistributionsTo)(x1To, x2To, x3To) = (*this->zeroDistributionsFrom)(x1From, x2From, x3From); +} +#endif + diff --git a/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h b/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..c57e1f6e069d35a01f07e00b9186cadfee3d537d --- /dev/null +++ b/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h @@ -0,0 +1,74 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LocalBlock3DConnector.h +//! \ingroup Connectors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef LocalBlock3DConnector_H +#define LocalBlock3DConnector_H + +#include "Block3DConnector.h" +#include "Block3D.h" +#include "PointerDefinitions.h" + +//! A class provides an interface for connectors in shared memory +class LocalBlock3DConnector : public Block3DConnector +{ +public: + LocalBlock3DConnector(SPtr<Block3D> from, SPtr<Block3D> to, int sendDir) + : Block3DConnector(sendDir) + , from(from) + , to(to) + { + + } + virtual ~LocalBlock3DConnector() {} + void sendTransmitterDataSize() {} + void receiveTransmitterDataSize() {} + virtual void init() = 0; + void prepareForReceive() {} + void prepareForSend() {} + void fillSendVectors() {} + virtual void sendVectors()=0; + void receiveVectors() {} + + void distributeReceiveVectors() {} + + bool isLocalConnector() { return true; } + bool isRemoteConnector() { return false; } + bool isInterpolationConnectorCF() { return false; } + bool isInterpolationConnectorFC() { return false; } + +protected: + WPtr<Block3D> from; + WPtr<Block3D> to; +}; + +#endif //LocalBlock3DConnector_H diff --git a/VirtualFluidsCore/Data/CMakePackage.txt b/VirtualFluidsCore/Data/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Data/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp b/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ed36627d4f2c9d7c1fa4532e0e8befe958bed36 --- /dev/null +++ b/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp @@ -0,0 +1,686 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27EsoTwist3DSplittedVector.cpp +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#include "D3Q27EsoTwist3DSplittedVector.h" +#include "EsoTwistD3Q27System.h" + +D3Q27EsoTwist3DSplittedVector::D3Q27EsoTwist3DSplittedVector() +{ +} +////////////////////////////////////////////////////////////////////////// +D3Q27EsoTwist3DSplittedVector::D3Q27EsoTwist3DSplittedVector( size_t nx1, size_t nx2, size_t nx3, LBMReal value ) +{ + this->NX1 = nx1; + this->NX2 = nx2; + this->NX3 = nx3; + + this->localDistributions = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1+1, nx2+1, nx3+1, value)); + this->nonLocalDistributions = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1+1, nx2+1, nx3+1, value)); + + this->restDistributions = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1, nx2, nx3, value)); +} +////////////////////////////////////////////////////////////////////////// +D3Q27EsoTwist3DSplittedVector::~D3Q27EsoTwist3DSplittedVector() +{ + +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::swap() +{ + std::swap( this->localDistributions, this->nonLocalDistributions ); +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3) +{ + f[D3Q27System::E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3); + f[D3Q27System::N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); + f[D3Q27System::T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3); + f[D3Q27System::NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3); + f[D3Q27System::NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3); + f[D3Q27System::TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3); + f[D3Q27System::TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3); + f[D3Q27System::TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3); + f[D3Q27System::TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3); + f[D3Q27System::TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3); + f[D3Q27System::TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3); + f[D3Q27System::TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3); + f[D3Q27System::TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3); + + f[D3Q27System::W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3 ); + f[D3Q27System::S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3 ); + f[D3Q27System::B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1 ); + f[D3Q27System::SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ); + f[D3Q27System::SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 ); + f[D3Q27System::BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 ); + f[D3Q27System::BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 ); + f[D3Q27System::BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 ); + f[D3Q27System::BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 ); + f[D3Q27System::BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); + f[D3Q27System::BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1); + f[D3Q27System::BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1); + f[D3Q27System::BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1); + + f[D3Q27System::REST] = (*this->restDistributions)(x1,x2,x3); +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3) +{ + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f[D3Q27System::INV_E]; + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f[D3Q27System::INV_N]; + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f[D3Q27System::INV_T]; + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f[D3Q27System::INV_NE]; + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f[D3Q27System::INV_NW]; + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f[D3Q27System::INV_TE]; + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f[D3Q27System::INV_TW]; + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f[D3Q27System::INV_TN]; + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f[D3Q27System::INV_TS]; + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f[D3Q27System::INV_TNE]; + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f[D3Q27System::INV_TNW]; + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f[D3Q27System::INV_TSE]; + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW]; + + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f[D3Q27System::INV_W ]; + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f[D3Q27System::INV_S ]; + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f[D3Q27System::INV_B ]; + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f[D3Q27System::INV_SW]; + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f[D3Q27System::INV_SE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f[D3Q27System::INV_BW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f[D3Q27System::INV_BE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f[D3Q27System::INV_BS]; + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f[D3Q27System::INV_BN]; + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f[D3Q27System::INV_BSE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f[D3Q27System::INV_BNW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1) = f[D3Q27System::INV_BNE]; + + (*this->restDistributions)(x1,x2,x3) = f[D3Q27System::REST]; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::getDistributionInv(LBMReal* const f, size_t x1, size_t x2, size_t x3) +{ + f[D3Q27System::INV_E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3); + f[D3Q27System::INV_N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); + f[D3Q27System::INV_T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3); + f[D3Q27System::INV_NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3); + f[D3Q27System::INV_NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3); + f[D3Q27System::INV_TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3); + f[D3Q27System::INV_TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3); + f[D3Q27System::INV_TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3); + f[D3Q27System::INV_TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3); + f[D3Q27System::INV_TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3); + f[D3Q27System::INV_TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3); + f[D3Q27System::INV_TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3); + f[D3Q27System::INV_TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3); + + f[D3Q27System::INV_W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3 ); + f[D3Q27System::INV_S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3 ); + f[D3Q27System::INV_B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1 ); + f[D3Q27System::INV_SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ); + f[D3Q27System::INV_SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 ); + f[D3Q27System::INV_BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 ); + f[D3Q27System::INV_BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 ); + f[D3Q27System::INV_BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 ); + f[D3Q27System::INV_BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 ); + f[D3Q27System::INV_BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); + f[D3Q27System::INV_BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1); + f[D3Q27System::INV_BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1); + f[D3Q27System::INV_BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1); + + f[D3Q27System::REST] = (*this->restDistributions)(x1,x2,x3); +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3) +{ + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f[D3Q27System::E]; + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f[D3Q27System::N]; + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f[D3Q27System::T]; + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f[D3Q27System::NE]; + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f[D3Q27System::NW]; + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f[D3Q27System::TE]; + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f[D3Q27System::TW]; + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f[D3Q27System::TN]; + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f[D3Q27System::TS]; + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f[D3Q27System::TNE]; + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f[D3Q27System::TNW]; + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f[D3Q27System::TSE]; + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW]; + + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f[D3Q27System::W ]; + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f[D3Q27System::S ]; + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f[D3Q27System::B ]; + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f[D3Q27System::SW]; + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f[D3Q27System::SE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f[D3Q27System::BW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f[D3Q27System::BE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f[D3Q27System::BS]; + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f[D3Q27System::BN]; + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f[D3Q27System::BSE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f[D3Q27System::BNW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1) = f[D3Q27System::BNE]; + + (*this->restDistributions)(x1,x2,x3) = f[D3Q27System::REST]; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) +{ + bool directionFlag = false; + if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE) + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f[D3Q27System::E]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW) + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f[D3Q27System::W]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS) + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f[D3Q27System::S]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN) + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f[D3Q27System::N]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB) + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f[D3Q27System::B]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT) + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f[D3Q27System::T]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW) + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f[D3Q27System::SW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE) + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f[D3Q27System::NE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW) + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f[D3Q27System::NW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE) + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f[D3Q27System::SE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW) + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f[D3Q27System::BW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE) + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f[D3Q27System::TE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW) + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f[D3Q27System::TW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE) + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f[D3Q27System::BE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS) + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f[D3Q27System::BS]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN) + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f[D3Q27System::TN]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS) + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f[D3Q27System::TS]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN) + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f[D3Q27System::BN]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW) + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f[D3Q27System::BSW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE) + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::TNE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE) + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f[D3Q27System::BSE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW) + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f[D3Q27System::TNW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW) + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f[D3Q27System::BNW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE) + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f[D3Q27System::TSE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE) + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::BNE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW) + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1) = f[D3Q27System::TSW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::REST) == EsoTwistD3Q27System::REST) + (*this->restDistributions)(x1,x2,x3) = f[D3Q27System::REST]; directionFlag=true; +#ifdef _DEBUG + if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); +#endif //DEBUG +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction) +{ + switch (direction) + { + case D3Q27System::E : + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f; + break; + case D3Q27System::W : + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f; + break; + case D3Q27System::S : + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f; + break; + case D3Q27System::N : + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f; + break; + case D3Q27System::B : + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f; + break; + case D3Q27System::T : + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f; + break; + case D3Q27System::SW : + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f; + break; + case D3Q27System::NE : + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f; + break; + case D3Q27System::NW : + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f; + break; + case D3Q27System::SE : + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f; + break; + case D3Q27System::BW : + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f; + break; + case D3Q27System::TE : + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f; + break; + case D3Q27System::TW : + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f; + break; + case D3Q27System::BE : + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f; + break; + case D3Q27System::BS : + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f; + break; + case D3Q27System::TN : + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f; + break; + case D3Q27System::TS : + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f; + break; + case D3Q27System::BN : + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f; + break; + case D3Q27System::BSW : + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f; + break; + case D3Q27System::TNE : + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f; + break; + case D3Q27System::BSE : + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f; + break; + case D3Q27System::TNW : + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f; + break; + case D3Q27System::BNW : + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f; + break; + case D3Q27System::TSE : + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f; + break; + case D3Q27System::BNE : + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f; + break; + case D3Q27System::TSW : + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1) = f; + break; + case D3Q27System::REST : + (*this->restDistributions)(x1,x2,x3) = f; + break; + default: + UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); + } +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) +{ + bool directionFlag = false; + if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE) + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f[D3Q27System::E]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW) + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f[D3Q27System::W]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS) + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f[D3Q27System::S]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN) + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f[D3Q27System::N]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB) + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f[D3Q27System::B]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT) + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f[D3Q27System::T]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW) + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f[D3Q27System::SW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE) + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f[D3Q27System::NE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW) + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f[D3Q27System::NW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE) + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f[D3Q27System::SE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW) + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f[D3Q27System::BW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE) + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f[D3Q27System::TE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW) + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f[D3Q27System::TW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE) + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f[D3Q27System::BE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS) + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f[D3Q27System::BS]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN) + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f[D3Q27System::TN]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS) + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f[D3Q27System::TS]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN) + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f[D3Q27System::BN]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW) + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE) + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f[D3Q27System::TNE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE) + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f[D3Q27System::BSE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW) + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f[D3Q27System::TNW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW) + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f[D3Q27System::BNW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE) + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f[D3Q27System::TSE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE) + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1)= f[D3Q27System::BNE]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW) + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW]; directionFlag=true; + if ((direction & EsoTwistD3Q27System::REST) == EsoTwistD3Q27System::REST) + (*this->restDistributions)(x1,x2,x3) = f[D3Q27System::REST]; directionFlag=true; +#ifdef _DEBUG + if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); +#endif //DEBUG +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction) +{ + switch (direction) + { + case D3Q27System::E : + (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3) = f; + break; + case D3Q27System::W : + (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ) = f; + break; + case D3Q27System::S : + (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ) = f; + break; + case D3Q27System::N : + (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3) = f; + break; + case D3Q27System::B : + (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ) = f; + break; + case D3Q27System::T : + (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3) = f; + break; + case D3Q27System::SW : + (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ) = f; + break; + case D3Q27System::NE : + (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3) = f; + break; + case D3Q27System::NW : + (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3) = f; + break; + case D3Q27System::SE : + (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ) = f; + break; + case D3Q27System::BW : + (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ) = f; + break; + case D3Q27System::TE : + (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3) = f; + break; + case D3Q27System::TW : + (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3) = f; + break; + case D3Q27System::BE : + (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ) = f; + break; + case D3Q27System::BS : + (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ) = f; + break; + case D3Q27System::TN : + (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3) = f; + break; + case D3Q27System::TS : + (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3) = f; + break; + case D3Q27System::BN : + (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ) = f; + break; + case D3Q27System::BSW : + (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f; + break; + case D3Q27System::TNE : + (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3) = f; + break; + case D3Q27System::BSE : + (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1) = f; + break; + case D3Q27System::TNW : + (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3) = f; + break; + case D3Q27System::BNW : + (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1) = f; + break; + case D3Q27System::TSE : + (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3) = f; + break; + case D3Q27System::BNE : + (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1) = f; + break; + case D3Q27System::TSW : + (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f; + break; + case D3Q27System::REST : + (*this->restDistributions)(x1,x2,x3) = f; + break; + default: + UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); + } +} +////////////////////////////////////////////////////////////////////////// +LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction) +{ + switch (direction) + { + case D3Q27System::W : + return (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ); + case D3Q27System::E : + return (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3); + case D3Q27System::N : + return (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3); + case D3Q27System::S : + return (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ); + case D3Q27System::T : + return (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3); + case D3Q27System::B : + return (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ); + case D3Q27System::NE : + return (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3); + case D3Q27System::SW : + return (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ); + case D3Q27System::SE : + return (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ); + case D3Q27System::NW : + return (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3); + case D3Q27System::TE : + return (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3); + case D3Q27System::BW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ); + case D3Q27System::BE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ); + case D3Q27System::TW : + return (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3); + case D3Q27System::TN : + return (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3); + case D3Q27System::BS : + return (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ); + case D3Q27System::BN : + return (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ); + case D3Q27System::TS : + return (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3); + case D3Q27System::TNE : + return (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3); + case D3Q27System::BSW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); + case D3Q27System::TNW : + return (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3); + case D3Q27System::BSE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1); + case D3Q27System::TSE : + return (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3); + case D3Q27System::BNW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1); + case D3Q27System::TSW : + return (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3); + case D3Q27System::BNE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1); + case D3Q27System::REST : + return (*this->restDistributions)(x1,x2,x3); + default: + UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); + } +} +////////////////////////////////////////////////////////////////////////// +LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction) +{ + switch (direction) + { + case D3Q27System::E : + return (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2, x3 ); + case D3Q27System::W : + return (*this->localDistributions)(D3Q27System::ET_E,x1, x2, x3); + case D3Q27System::S : + return (*this->localDistributions)(D3Q27System::ET_N,x1, x2, x3); + case D3Q27System::N : + return (*this->nonLocalDistributions)(D3Q27System::ET_S,x1, x2+1,x3 ); + case D3Q27System::B : + return (*this->localDistributions)(D3Q27System::ET_T,x1, x2, x3); + case D3Q27System::T : + return (*this->nonLocalDistributions)(D3Q27System::ET_B,x1, x2, x3+1 ); + case D3Q27System::SW : + return (*this->localDistributions)(D3Q27System::ET_NE,x1, x2, x3); + case D3Q27System::NE : + return (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 ); + case D3Q27System::NW : + return (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1, x2+1,x3 ); + case D3Q27System::SE : + return (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2, x3); + case D3Q27System::BW : + return (*this->localDistributions)(D3Q27System::ET_TE,x1, x2, x3); + case D3Q27System::TE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2, x3+1 ); + case D3Q27System::TW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1, x2, x3+1 ); + case D3Q27System::BE : + return (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2, x3); + case D3Q27System::BS : + return (*this->localDistributions)(D3Q27System::ET_TN,x1, x2, x3); + case D3Q27System::TN : + return (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1, x2+1,x3+1 ); + case D3Q27System::TS : + return (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1, x2, x3+1 ); + case D3Q27System::BN : + return (*this->localDistributions)(D3Q27System::ET_TS,x1, x2+1,x3); + case D3Q27System::BSW : + return (*this->localDistributions)(D3Q27System::ET_TNE,x1, x2, x3); + case D3Q27System::TNE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); + case D3Q27System::BSE : + return (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2, x3); + case D3Q27System::TNW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1, x2+1,x3+1); + case D3Q27System::BNW : + return (*this->localDistributions)(D3Q27System::ET_TSE,x1, x2+1,x3); + case D3Q27System::TSE : + return (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2, x3+1); + case D3Q27System::BNE : + return (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3); + case D3Q27System::TSW : + return (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1, x2, x3+1); + case D3Q27System::REST : + return (*this->restDistributions)(x1,x2,x3); + default: + UB_THROW( UbException(UB_EXARGS, "Direction didn't find") ); + } +} +////////////////////////////////////////////////////////////////////////// +size_t D3Q27EsoTwist3DSplittedVector::getNX1() const +{ + return NX1; +} +////////////////////////////////////////////////////////////////////////// +size_t D3Q27EsoTwist3DSplittedVector::getNX2() const +{ + return NX2; +} +////////////////////////////////////////////////////////////////////////// +size_t D3Q27EsoTwist3DSplittedVector::getNX3() const +{ + return NX3; +} +////////////////////////////////////////////////////////////////////////// +CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr D3Q27EsoTwist3DSplittedVector::getLocalDistributions() +{ + return this->localDistributions; +} +////////////////////////////////////////////////////////////////////////// +CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr D3Q27EsoTwist3DSplittedVector::getNonLocalDistributions() +{ + return this->nonLocalDistributions; +} +////////////////////////////////////////////////////////////////////////// +CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr D3Q27EsoTwist3DSplittedVector::getZeroDistributions() +{ + return this->restDistributions; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setNX1(size_t newNX1) +{ + NX1 = newNX1; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setNX2(size_t newNX2) +{ + NX2 = newNX2; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setNX3(size_t newNX3) +{ + NX3 = newNX3; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setLocalDistributions(CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr array) +{ + localDistributions = array; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setNonLocalDistributions(CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr array) +{ + nonLocalDistributions = array; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27EsoTwist3DSplittedVector::setZeroDistributions(CbArray3D<LBMReal, IndexerX3X2X1>::CbArray3DPtr array) +{ + restDistributions = array; +} + +////////////////////////////////////////////////////////////////////////// + diff --git a/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h b/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h new file mode 100644 index 0000000000000000000000000000000000000000..725b845d0ac9776979c017f2a1caab9e903077d9 --- /dev/null +++ b/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h @@ -0,0 +1,108 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27EsoTwist3DSplittedVector.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef D3Q27EsoTwist3DSplittedVector_h +#define D3Q27EsoTwist3DSplittedVector_h + +#include "EsoTwist3D.h" +#include "D3Q27System.h" +#include "basics/container/CbArray4D.h" +#include "basics/container/CbArray3D.h" + +//! \brief Class implements EsoTwist3D +//! \details D3Q27EsoTwist3DSplittedVector uses three vectors to implement Esoteric Twist method +class D3Q27EsoTwist3DSplittedVector : public EsoTwist3D +{ +public: + D3Q27EsoTwist3DSplittedVector(); + //! \param nx1 number of nodes in x1 direction + //! \param nx2 number of nodes in x2 direction + //! \param nx3 number of nodes in x3 direction + //! \param value initialisation value + D3Q27EsoTwist3DSplittedVector(size_t nx1, size_t nx2, size_t nx3, LBMReal value); + ////////////////////////////////////////////////////////////////////////// + ~D3Q27EsoTwist3DSplittedVector(); + ////////////////////////////////////////////////////////////////////////// + void swap(); + ////////////////////////////////////////////////////////////////////////// + virtual void getDistribution( LBMReal* const f, size_t x1, size_t x2, size_t x3); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3); + //////////////////////////////////////////////////////////////////////// + virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction); + ////////////////////////////////////////////////////////////////////////// + virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction); + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction); + ////////////////////////////////////////////////////////////////////////// + virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction); + ////////////////////////////////////////////////////////////////////////// + size_t getNX1() const; + ////////////////////////////////////////////////////////////////////////// + size_t getNX2() const; + ////////////////////////////////////////////////////////////////////////// + size_t getNX3() const; + ////////////////////////////////////////////////////////////////////////// + CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr getLocalDistributions(); + ////////////////////////////////////////////////////////////////////////// + CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr getNonLocalDistributions(); + ////////////////////////////////////////////////////////////////////////// + CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr getZeroDistributions(); + ////////////////////////////////////////////////////////////////////////// + void setNX1(size_t newNX1); + void setNX2(size_t newNX2); + void setNX3(size_t newNX3); + void setLocalDistributions(CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr array); + void setNonLocalDistributions(CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr array); + void setZeroDistributions(CbArray3D<LBMReal, IndexerX3X2X1>::CbArray3DPtr array); + +protected: + CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions; + CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions; + CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr restDistributions; + size_t NX1, NX2, NX3; + + friend class MPIIORestartCoProcessor; + friend class MPIIOMigrationCoProcessor; + +}; + +#endif diff --git a/VirtualFluidsCore/Data/DataSet3D.h b/VirtualFluidsCore/Data/DataSet3D.h new file mode 100644 index 0000000000000000000000000000000000000000..296a15065bfc74c3fa9d7862207dacebb9509361 --- /dev/null +++ b/VirtualFluidsCore/Data/DataSet3D.h @@ -0,0 +1,169 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file DataSet3D.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef DataSet3D_h +#define DataSet3D_h + +#include <PointerDefinitions.h> + +#include "basics/container/CbArray4D.h" +#include "basics/container/CbArray3D.h" +#include "DistributionArray3D.h" + +typedef CbArray4D<LBMReal,IndexerX4X3X2X1> AverageValuesArray3D; +typedef CbArray4D<LBMReal,IndexerX4X3X2X1> ShearStressValuesArray3D; +typedef CbArray3D<LBMReal, IndexerX3X2X1> RelaxationFactorArray3D; + +//! A class provides an interface for data structures in the kernel. +class DataSet3D +{ +public: + SPtr<DistributionArray3D> getFdistributions() const; + void setFdistributions(SPtr<DistributionArray3D> distributions); + + SPtr<AverageValuesArray3D> getAverageDensity() const; + void setAverageDensity(SPtr<AverageValuesArray3D> values); + + SPtr<AverageValuesArray3D> getAverageVelocity() const; + void setAverageVelocity(SPtr<AverageValuesArray3D> values); + + SPtr<AverageValuesArray3D> getAverageFluctuations() const; + void setAverageFluctuations(SPtr<AverageValuesArray3D> values); + + SPtr<AverageValuesArray3D> getAverageTriplecorrelations() const; + void setAverageTriplecorrelations(SPtr<AverageValuesArray3D> values); + + SPtr<AverageValuesArray3D> getAverageValues() const; + void setAverageValues(SPtr<AverageValuesArray3D> values); + + SPtr<ShearStressValuesArray3D> getShearStressValues() const; + void setShearStressValues(SPtr<ShearStressValuesArray3D> values); + + SPtr<RelaxationFactorArray3D> getRelaxationFactor() const; + void setRelaxationFactor(SPtr<RelaxationFactorArray3D> values); +protected: +private: + SPtr<DistributionArray3D> fdistributions; + SPtr<AverageValuesArray3D> averageValues; + + SPtr<AverageValuesArray3D> averageDensity; + SPtr<AverageValuesArray3D> averageVelocity; + SPtr<AverageValuesArray3D> averageFluktuations; + SPtr<AverageValuesArray3D> averageTriplecorrelations; + + SPtr<ShearStressValuesArray3D> shearStressValues; + + SPtr<RelaxationFactorArray3D> relaxationFactor; + +}; + +inline SPtr<DistributionArray3D> DataSet3D::getFdistributions() const +{ + return fdistributions; +} + +inline void DataSet3D::setFdistributions(SPtr<DistributionArray3D> distributions) +{ + fdistributions = distributions; +} + +inline SPtr<AverageValuesArray3D> DataSet3D::getAverageValues() const +{ + return averageValues; +} + +inline void DataSet3D::setAverageValues(SPtr<AverageValuesArray3D> values) +{ + averageValues = values; +} + +inline SPtr<AverageValuesArray3D> DataSet3D::getAverageDensity() const +{ + return averageDensity; +} + +inline void DataSet3D::setAverageDensity(SPtr<AverageValuesArray3D> values) +{ + averageDensity = values; +} + +inline SPtr<AverageValuesArray3D> DataSet3D::getAverageVelocity() const +{ + return averageVelocity; +} + +inline void DataSet3D::setAverageVelocity(SPtr<AverageValuesArray3D> values) +{ + averageVelocity = values; +} + +inline SPtr<AverageValuesArray3D> DataSet3D::getAverageFluctuations() const +{ + return averageFluktuations; +} + +inline void DataSet3D::setAverageFluctuations(SPtr<AverageValuesArray3D> values) +{ + averageFluktuations = values; +} + +inline SPtr<AverageValuesArray3D> DataSet3D::getAverageTriplecorrelations() const +{ + return averageTriplecorrelations; +} + +inline void DataSet3D::setAverageTriplecorrelations(SPtr<AverageValuesArray3D> values) +{ + averageTriplecorrelations = values; +} + +inline SPtr<ShearStressValuesArray3D> DataSet3D::getShearStressValues() const +{ + return shearStressValues; +} + +inline void DataSet3D::setShearStressValues(SPtr<ShearStressValuesArray3D> values) +{ + shearStressValues = values; +} + +inline SPtr<RelaxationFactorArray3D> DataSet3D::getRelaxationFactor() const +{ + return relaxationFactor; +} + +inline void DataSet3D::setRelaxationFactor(SPtr<RelaxationFactorArray3D> values) +{ + relaxationFactor = values; +} +#endif diff --git a/VirtualFluidsCore/Data/DistributionArray3D.h b/VirtualFluidsCore/Data/DistributionArray3D.h new file mode 100644 index 0000000000000000000000000000000000000000..4e333b5046d73b2aee355e7657725acfbe8cb336 --- /dev/null +++ b/VirtualFluidsCore/Data/DistributionArray3D.h @@ -0,0 +1,92 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file DistributionArray3D.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef DistributionArray3D_H +#define DistributionArray3D_H + +#include <LBMSystem.h> + +//! \brief Abstract class of data structure for LBM +class DistributionArray3D +{ +public: + DistributionArray3D() {}; + virtual ~DistributionArray3D(){}; + //! get number of nodes for x1 direction + virtual size_t getNX1() const = 0; + //! get number of nodes for x2 direction + virtual size_t getNX2() const = 0; + //! get number of nodes for x3 direction + virtual size_t getNX3() const = 0; + //! get distribution + //! \param f distribution + //! \param x1 coordinate x1 + //! \param x2 coordinate x2 + //! \param x3 coordinate x3 + virtual void getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + //! set distribution + //! \param f distribution + //! \param x1 coordinate x1 + //! \param x2 coordinate x2 + //! \param x3 coordinate x3 + virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + //! get distribution in inverse order + //! \param f distribution + //! \param x1 coordinate x1 + //! \param x2 coordinate x2 + //! \param x3 coordinate x3 + virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + //! set distribution in inverse order + //! \param f distribution + //! \param x1 coordinate x1 + //! \param x1 coordinate x2 + //! \param x1 coordinate x3 + virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + //! set distribution in inverse order + //! \param f distribution + //! \param x1 coordinate x1 + //! \param x1 coordinate x2 + //! \param x1 coordinate x3 + virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction) = 0; + virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0; + virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0; + virtual void swap() = 0; +protected: +private: + +}; + +#endif diff --git a/VirtualFluidsCore/Data/EsoTwist3D.h b/VirtualFluidsCore/Data/EsoTwist3D.h new file mode 100644 index 0000000000000000000000000000000000000000..6b1178aaa33977751518a63011b2efe3e4202e1e --- /dev/null +++ b/VirtualFluidsCore/Data/EsoTwist3D.h @@ -0,0 +1,84 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file EsoTwist3D.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef ESOTWIST3D_H +#define ESOTWIST3D_H + +#include "DistributionArray3D.h" +#include <LBMSystem.h> + +//! \brief Abstract class for implementation of Esoteric Twist method +//! \details EsoTwist3D provide an interface for different implementations of Esoteric Twist method +//! <a href="https://doi.org/10.3390/computation5020019"><b>[ Geier et al., (2017), 10.3390/computation5020019]</b></a> +// Geier, M., & Schönherr, M. (2017). Esoteric twist: an efficient in-place streaming algorithmus for the lattice Boltzmann method on massively parallel hardware. Computation, 5(2), 19. + +class EsoTwist3D : public DistributionArray3D +{ +public: + EsoTwist3D(){}; + virtual ~EsoTwist3D(){}; + ////////////////////////////////////////////////////////////////////////// + virtual void swap() = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + //////////////////////////////////////////////////////////////////////// + virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + //virtual void getDistributionInvForDirection(LBMReal* const& f, const size_t& x1, const size_t& x2, const size_t& x3, const unsigned long int& direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0; + ////////////////////////////////////////////////////////////////////////// + virtual size_t getNX1() const = 0; + ////////////////////////////////////////////////////////////////////////// + virtual size_t getNX2() const = 0; + ////////////////////////////////////////////////////////////////////////// + virtual size_t getNX3() const = 0; + ////////////////////////////////////////////////////////////////////////// + +}; + +#endif diff --git a/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp b/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5924dc2f93445ea7c6e748169d17fc3671404640 --- /dev/null +++ b/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp @@ -0,0 +1,125 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file EsoTwistD3Q27System.cpp +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#include "EsoTwistD3Q27System.h" + +//index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 +//f: E, W, N, S, T, B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW REST +const int EsoTwistD3Q27System::ETX1[EsoTwistD3Q27System::ENDF+1] = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; +const int EsoTwistD3Q27System::ETX2[EsoTwistD3Q27System::ENDF+1] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0 }; +const int EsoTwistD3Q27System::ETX3[EsoTwistD3Q27System::ENDF+1] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, -1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 1, 0, 1, 0 }; + +const int EsoTwistD3Q27System::etINVDIR[EsoTwistD3Q27System::ENDF+1] = { D3Q27System::INV_E, + D3Q27System::INV_W, + D3Q27System::INV_N, + D3Q27System::INV_S, + D3Q27System::INV_T, + D3Q27System::INV_B, + D3Q27System::INV_NE, + D3Q27System::INV_SW, + D3Q27System::INV_SE, + D3Q27System::INV_NW, + D3Q27System::INV_TE, + D3Q27System::INV_BW, + D3Q27System::INV_BE, + D3Q27System::INV_TW, + D3Q27System::INV_TN, + D3Q27System::INV_BS, + D3Q27System::INV_BN, + D3Q27System::INV_TS, + D3Q27System::INV_TNE, + D3Q27System::INV_TNW, + D3Q27System::INV_TSE, + D3Q27System::INV_TSW, + D3Q27System::INV_BNE, + D3Q27System::INV_BNW, + D3Q27System::INV_BSE, + D3Q27System::INV_BSW, + D3Q27System::REST}; + +const unsigned long int EsoTwistD3Q27System::etDIR[EsoTwistD3Q27System::ENDF+1] = { etE, + etW, + etN, + etS, + etT, + etB, + etNE, + etSW, + etSE, + etNW, + etTE, + etBW, + etBE, + etTW, + etTN, + etBS, + etBN, + etTS, + etTNE, + etTNW, + etTSE, + etTSW, + etBNE, + etBNW, + etBSE, + etBSW, + etZERO}; + + const unsigned long int EsoTwistD3Q27System::etZERO = 1;/*f0 */ + const unsigned long int EsoTwistD3Q27System::etE = 2; /*f1 */ + const unsigned long int EsoTwistD3Q27System::etW = 4; /*f2 */ + const unsigned long int EsoTwistD3Q27System::etN = 8; /*f3 */ + const unsigned long int EsoTwistD3Q27System::etS = 16; /*f4 */ + const unsigned long int EsoTwistD3Q27System::etT = 32; /*f5 */ + const unsigned long int EsoTwistD3Q27System::etB = 64; /*f6 */ + const unsigned long int EsoTwistD3Q27System::etNE = 128; /*f7 */ + const unsigned long int EsoTwistD3Q27System::etSW = 256; /*f8 */ + const unsigned long int EsoTwistD3Q27System::etSE = 512; /*f9 */ + const unsigned long int EsoTwistD3Q27System::etNW = 1024; /*f10*/ + const unsigned long int EsoTwistD3Q27System::etTE = 2048; /*f11*/ + const unsigned long int EsoTwistD3Q27System::etBW = 4096; /*f12*/ + const unsigned long int EsoTwistD3Q27System::etBE = 8192; /*f13*/ + const unsigned long int EsoTwistD3Q27System::etTW = 16384; /*f14*/ + const unsigned long int EsoTwistD3Q27System::etTN = 32768; /*f15*/ + const unsigned long int EsoTwistD3Q27System::etBS = 65536; /*f16*/ + const unsigned long int EsoTwistD3Q27System::etBN = 131072; /*f17*/ + const unsigned long int EsoTwistD3Q27System::etTS = 262144; /*f18*/ + const unsigned long int EsoTwistD3Q27System::etTNE = 524288; + const unsigned long int EsoTwistD3Q27System::etTNW = 1048576; + const unsigned long int EsoTwistD3Q27System::etTSE = 2097152; + const unsigned long int EsoTwistD3Q27System::etTSW = 4194304; + const unsigned long int EsoTwistD3Q27System::etBNE = 8388608; + const unsigned long int EsoTwistD3Q27System::etBNW = 16777216; + const unsigned long int EsoTwistD3Q27System::etBSE = 33554432; +const unsigned long int EsoTwistD3Q27System::etBSW = 67108864; + diff --git a/VirtualFluidsCore/Data/EsoTwistD3Q27System.h b/VirtualFluidsCore/Data/EsoTwistD3Q27System.h new file mode 100644 index 0000000000000000000000000000000000000000..290abf4d06e843cc79b4597dc2d1e745bdd91f6d --- /dev/null +++ b/VirtualFluidsCore/Data/EsoTwistD3Q27System.h @@ -0,0 +1,142 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file EsoTwistD3Q27System.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef ESOTWISTD3Q27SYSTEM_H +#define ESOTWISTD3Q27SYSTEM_H + +#include "D3Q27System.h" + +//! +struct EsoTwistD3Q27System +{ + const static int FSTARTDIR = D3Q27System::FSTARTDIR; + const static int FENDDIR = D3Q27System::FENDDIR; //gellerstyle: meint alle frichtungen OHNE f0 + + const static int STARTF = D3Q27System::STARTF; + const static int ENDF = D3Q27System::ENDF; + + const static int STARTDIR = D3Q27System::STARTDIR; + const static int ENDDIR = D3Q27System::ENDDIR; + + static const int REST = D3Q27System::REST;/*f0 */ + static const int E = D3Q27System::E; /*f1 */ + static const int W = D3Q27System::W; /*f2 */ + static const int N = D3Q27System::N; /*f3 */ + static const int S = D3Q27System::S; /*f4 */ + static const int T = D3Q27System::T; /*f5 */ + static const int B = D3Q27System::B; /*f6 */ + static const int NE = D3Q27System::NE; /*f7 */ + static const int SW = D3Q27System::SW; /*f8 */ + static const int SE = D3Q27System::SE; /*f9 */ + static const int NW = D3Q27System::NW; /*f10*/ + static const int TE = D3Q27System::TE; /*f11*/ + static const int BW = D3Q27System::BW; /*f12*/ + static const int BE = D3Q27System::BE; /*f13*/ + static const int TW = D3Q27System::TW; /*f14*/ + static const int TN = D3Q27System::TN; /*f15*/ + static const int BS = D3Q27System::BS; /*f16*/ + static const int BN = D3Q27System::BN; /*f17*/ + static const int TS = D3Q27System::TS; /*f18*/ + static const int TNE = D3Q27System::TNE; + static const int TNW = D3Q27System::TNW; + static const int TSE = D3Q27System::TSE; + static const int TSW = D3Q27System::TSW; + static const int BNE = D3Q27System::BNE; + static const int BNW = D3Q27System::BNW; + static const int BSE = D3Q27System::BSE; + static const int BSW = D3Q27System::BSW; + + + static const int INV_E = D3Q27System::W; + static const int INV_W = D3Q27System::E; + static const int INV_N = D3Q27System::S; + static const int INV_S = D3Q27System::N; + static const int INV_T = D3Q27System::B; + static const int INV_B = D3Q27System::T; + static const int INV_NE = D3Q27System::SW; + static const int INV_SW = D3Q27System::NE; + static const int INV_SE = D3Q27System::NW; + static const int INV_NW = D3Q27System::SE; + static const int INV_TE = D3Q27System::BW; + static const int INV_BW = D3Q27System::TE; + static const int INV_BE = D3Q27System::TW; + static const int INV_TW = D3Q27System::BE; + static const int INV_TN = D3Q27System::BS; + static const int INV_BS = D3Q27System::TN; + static const int INV_BN = D3Q27System::TS; + static const int INV_TS = D3Q27System::BN; + static const int INV_TNE = D3Q27System::BSW; + static const int INV_TNW = D3Q27System::BSE; + static const int INV_TSE = D3Q27System::BNW; + static const int INV_TSW = D3Q27System::BNE; + static const int INV_BNE = D3Q27System::TSW; + static const int INV_BNW = D3Q27System::TSE; + static const int INV_BSE = D3Q27System::TNW; + static const int INV_BSW = D3Q27System::TNE; + + static const unsigned long int etZERO;// 1;/*f0 */ + static const unsigned long int etE;// 2; /*f1 */ + static const unsigned long int etW;// 4; /*f2 */ + static const unsigned long int etN;// 8; /*f3 */ + static const unsigned long int etS;// 16; /*f4 */ + static const unsigned long int etT;// 32; /*f5 */ + static const unsigned long int etB;// 64; /*f6 */ + static const unsigned long int etNE;// 128; /*f7 */ + static const unsigned long int etSW;// 256; /*f8 */ + static const unsigned long int etSE;// 512; /*f9 */ + static const unsigned long int etNW;// 1024; /*f10*/ + static const unsigned long int etTE;// 2048; /*f11*/ + static const unsigned long int etBW;// 4096; /*f12*/ + static const unsigned long int etBE;// 8192; /*f13*/ + static const unsigned long int etTW;// 16384; /*f14*/ + static const unsigned long int etTN;// 32768; /*f15*/ + static const unsigned long int etBS;// 65536; /*f16*/ + static const unsigned long int etBN;// 131072; /*f17*/ + static const unsigned long int etTS;// 262144; /*f18*/ + static const unsigned long int etTNE;// 524288; + static const unsigned long int etTNW;// 1048576; + static const unsigned long int etTSE;// 2097152; + static const unsigned long int etTSW;// 4194304; + static const unsigned long int etBNE;// 8388608; + static const unsigned long int etBNW;// 16777216; + static const unsigned long int etBSE;// 33554432; + static const unsigned long int etBSW;// = 67108864; + + const static int ETX1[ENDF+1]; + const static int ETX2[ENDF+1]; + const static int ETX3[ENDF+1]; + const static int etINVDIR[ENDF+1]; + const static unsigned long int etDIR[ENDF+1]; +}; + +#endif diff --git a/VirtualFluidsCore/Grid/BasicCalculator.cpp b/VirtualFluidsCore/Grid/BasicCalculator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a2ee9647cf9700cca5bb0e7139eb821d4eef19a --- /dev/null +++ b/VirtualFluidsCore/Grid/BasicCalculator.cpp @@ -0,0 +1,400 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BasicCalculator.cpp +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#include "BasicCalculator.h" + +#include "Block3D.h" +#include "BCProcessor.h" +#include "LBMKernel.h" +#include "Block3DConnector.h" +#include "UbScheduler.h" +#include "UbLogger.h" + +#ifdef _OPENMP +#include <omp.h> +#endif +#define OMP_SCHEDULE guided + +//#define TIMING +//#include "UbTiming.h" + +BasicCalculator::BasicCalculator(SPtr<Grid3D> grid, SPtr<UbScheduler> additionalGhostLayerUpdateScheduler, int numberOfTimeSteps) : + Calculator(grid, additionalGhostLayerUpdateScheduler, numberOfTimeSteps) +{ + +} +////////////////////////////////////////////////////////////////////////// +BasicCalculator::~BasicCalculator() +{ + +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::calculate() +{ + UBLOG(logDEBUG1, "BasicCalculator::calculate() - started"); + int calcStep = 0; + try + { + int minInitLevel = minLevel; + int maxInitLevel = maxLevel-minLevel; + int straightStartLevel = minInitLevel; + int internalIterations = 1<<(maxInitLevel-minInitLevel); + int forwardStartLevel; + int threshold; + +#ifdef TIMING + UbTimer timer; + double time[6]; +#endif + + for (calcStep = startTimeStep; calcStep<=numberOfTimeSteps; calcStep++) + { + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + UBLOG(logINFO, "calcStep = "<<calcStep); +#endif + ////////////////////////////////////////////////////////////////////////// + + for (int staggeredStep = 1; staggeredStep<=internalIterations; staggeredStep++) + { + forwardStartLevel = straightStartLevel; + if (staggeredStep==internalIterations) straightStartLevel = minInitLevel; + else + { + for (straightStartLevel = maxInitLevel, threshold = 1; + (staggeredStep&threshold)!=threshold; straightStartLevel--, threshold <<= 1); + } + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + timer.resetAndStart(); +#endif + ////////////////////////////////////////////////////////////////////////// + applyPreCollisionBC(straightStartLevel, maxInitLevel); + + //do collision for all blocks + calculateBlocks(straightStartLevel, maxInitLevel, calcStep); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[0] = timer.stop(); + UBLOG(logINFO, "calculateBlocks time = "<<time[0]); +#endif + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + //exchange data between blocks + exchangeBlockData(straightStartLevel, maxInitLevel); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[1] = timer.stop(); + UBLOG(logINFO, "exchangeBlockData time = "<<time[1]); +#endif + ////////////////////////////////////////////////////////////////////////// + applyPostCollisionBC(straightStartLevel, maxInitLevel); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[2] = timer.stop(); + UBLOG(logINFO, "applyBCs time = "<<time[2]); +#endif + ////////////////////////////////////////////////////////////////////////// + //swap distributions in kernel + swapDistributions(straightStartLevel, maxInitLevel); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[3] = timer.stop(); + UBLOG(logINFO, "swapDistributions time = "<<time[3]); +#endif + ////////////////////////////////////////////////////////////////////////// + if (refinement) + { + if (straightStartLevel<maxInitLevel) + exchangeBlockData(straightStartLevel, maxInitLevel); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[4] = timer.stop(); + UBLOG(logINFO, "refinement exchangeBlockData time = "<<time[4]); +#endif + ////////////////////////////////////////////////////////////////////////// + //now ghost nodes have actual values + //interpolation of interface nodes between grid levels + interpolation(straightStartLevel, maxInitLevel); + ////////////////////////////////////////////////////////////////////////// +#ifdef TIMING + time[5] = timer.stop(); + UBLOG(logINFO, "refinement interpolation time = "<<time[5]); +#endif + ////////////////////////////////////////////////////////////////////////// + } + } + //exchange data between blocks for visualization + if (additionalGhostLayerUpdateScheduler->isDue(calcStep)) + { + exchangeBlockData(straightStartLevel, maxInitLevel); + } + coProcess((double)(calcStep)); + //now ghost nodes have actual values + } + UBLOG(logDEBUG1, "BasicCalculator::calculate() - stoped"); + } + catch (std::exception& e) + { + UBLOG(logERROR, e.what()); + UBLOG(logERROR, " step = "<<calcStep); + //throw; + exit(EXIT_FAILURE); + } + catch (std::string& s) + { + UBLOG(logERROR, s); + exit(EXIT_FAILURE); + } + catch (...) + { + UBLOG(logERROR, "unknown exception"); + exit(EXIT_FAILURE); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::calculateBlocks(int startLevel, int maxInitLevel, int calcStep) +{ +#ifdef _OPENMP +#pragma omp parallel +#endif + { + SPtr<Block3D> blockTemp; + try + { + //startLevel bis maxInitLevel + for (int level = startLevel; level<=maxInitLevel; level++) + { + //timer.resetAndStart(); + //call LBM kernel + int size = (int)blocks[level].size(); +#ifdef _OPENMP +#pragma omp for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + blockTemp = blocks[level][i]; + blockTemp->getKernel()->calculate(calcStep); + } + //timer.stop(); + //UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size() << " collision time = " << timer.getTotalTime()); + } + } + catch (std::exception& e) + { + UBLOG(logERROR, e.what()); + //UBLOG(logERROR, blockTemp->toString()<<" step = "<<calcStep); + //throw; + exit(EXIT_FAILURE); + } + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::exchangeBlockData(int startLevel, int maxInitLevel) +{ + //startLevel bis maxInitLevel + for (int level = startLevel; level<=maxInitLevel; level++) + { + //connectorsPrepareLocal(localConns[level]); + connectorsSendLocal(localConns[level]); + //connectorsReceiveLocal(localConns[level]); + + connectorsPrepareRemote(remoteConns[level]); + connectorsSendRemote(remoteConns[level]); + connectorsReceiveRemote(remoteConns[level]); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::swapDistributions(int startLevel, int maxInitLevel) +{ +#ifdef _OPENMP +#pragma omp parallel +#endif + { + //from startLevel to maxInitLevel + for (int level = startLevel; level<=maxInitLevel; level++) + { + int size = (int)blocks[level].size(); +#ifdef _OPENMP +#pragma omp for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + blocks[level][i]->getKernel()->swapDistributions(); + } + } + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::connectorsPrepareLocal(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); +#ifdef _OPENMP +#pragma omp parallel for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + connectors[i]->prepareForReceive(); + connectors[i]->prepareForSend(); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::connectorsSendLocal(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); +#ifdef _OPENMP +#pragma omp parallel for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + connectors[i]->fillSendVectors(); + connectors[i]->sendVectors(); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::connectorsReceiveLocal(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); +#ifdef _OPENMP +#pragma omp parallel for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + connectors[i]->receiveVectors(); + connectors[i]->distributeReceiveVectors(); + } +} +void BasicCalculator::connectorsPrepareRemote(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); + for (int i =0; i<size; i++) + { + connectors[i]->prepareForReceive(); + connectors[i]->prepareForSend(); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::connectorsSendRemote(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); + for (int i =0; i<size; i++) + { + connectors[i]->fillSendVectors(); + connectors[i]->sendVectors(); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::connectorsReceiveRemote(std::vector< SPtr<Block3DConnector> >& connectors) +{ + int size = (int)connectors.size(); + for (int i =0; i<size; i++) + { + connectors[i]->receiveVectors(); + connectors[i]->distributeReceiveVectors(); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::interpolation(int startLevel, int maxInitLevel) +{ + for (int level = startLevel; level<maxInitLevel; level++) + { + connectorsPrepareLocal(localInterConns[level]); + connectorsPrepareRemote(remoteInterConns[level]); + } + + for (int level = startLevel; level<maxInitLevel; level++) + { + connectorsSendLocal(localInterConns[level]); + connectorsSendRemote(remoteInterConns[level]); + } + + for (int level = startLevel; level<maxInitLevel; level++) + { + connectorsReceiveLocal(localInterConns[level]); + connectorsReceiveRemote(remoteInterConns[level]); + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::applyPreCollisionBC(int startLevel, int maxInitLevel) +{ + //from startLevel to maxInitLevel + for (int level = startLevel; level<=maxInitLevel; level++) + { + int size = (int)blocks[level].size(); +#ifdef _OPENMP +#pragma omp parallel for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + blocks[level][i]->getKernel()->getBCProcessor()->applyPreCollisionBC(); + } + } +} +////////////////////////////////////////////////////////////////////////// +void BasicCalculator::applyPostCollisionBC(int startLevel, int maxInitLevel) +{ + try{ + //from startLevel to maxInitLevel + for (int level = startLevel; level<=maxInitLevel; level++) + { + int size = (int)blocks[level].size(); +#ifdef _OPENMP +#pragma omp parallel for schedule(OMP_SCHEDULE) +#endif + for (int i =0; i<size; i++) + { + blocks[level][i]->getKernel()->getBCProcessor()->applyPostCollisionBC(); + } + } +} + catch (std::exception& e) + { + UBLOG(logERROR, e.what()); + //UBLOG(logERROR, " step = "<<calcStep); + //throw; + exit(EXIT_FAILURE); + } + catch (std::string& s) + { + UBLOG(logERROR, s); + //throw; + exit(EXIT_FAILURE); + } + catch (...) + { + UBLOG(logERROR, "unknown exception"); + //throw; + exit(EXIT_FAILURE); + } +} + diff --git a/VirtualFluidsCore/Grid/BasicCalculator.h b/VirtualFluidsCore/Grid/BasicCalculator.h new file mode 100644 index 0000000000000000000000000000000000000000..8137a21c37d6972d40919bb7ae1cc45199edfc56 --- /dev/null +++ b/VirtualFluidsCore/Grid/BasicCalculator.h @@ -0,0 +1,70 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BasicCalculator.h +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BasicCalculator_h__ +#define BasicCalculator_h__ + +#include "Calculator.h" + +class Block3DConnector; + +//! \class BasicCalculator +//! \brief Class implements basic functionality with OpenMP parallelization for main calculation LBM loop + +class BasicCalculator : public Calculator +{ +public: + BasicCalculator(SPtr<Grid3D> grid, SPtr<UbScheduler> additionalGhostLayerUpdateScheduler, int numberOfTimeSteps); + virtual ~BasicCalculator(); + virtual void calculate(); + +protected: + void calculateBlocks(int startLevel, int maxInitLevel, int calcStep); + void swapDistributions(int startLevel, int maxInitLevel); + void exchangeBlockData(int startLevel, int maxInitLevel); + void connectorsPrepareLocal(std::vector< SPtr<Block3DConnector> >& connectors); + void connectorsSendLocal(std::vector< SPtr<Block3DConnector> >& connectors); + void connectorsReceiveLocal(std::vector< SPtr<Block3DConnector> >& connectors); + void connectorsPrepareRemote(std::vector< SPtr<Block3DConnector> >& connectors); + void connectorsSendRemote(std::vector< SPtr<Block3DConnector> >& connectors); + void connectorsReceiveRemote(std::vector< SPtr<Block3DConnector> >& connectors); + void interpolation(int startLevel, int maxInitLevel); + void applyPreCollisionBC(int startLevel, int maxInitLevel); + void applyPostCollisionBC(int startLevel, int maxInitLevel); +private: +}; + +#endif // BasicCalculator_h__ + + + diff --git a/VirtualFluidsCore/Grid/Block3D.cpp b/VirtualFluidsCore/Grid/Block3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0aa676dc38a2438ff5ba500bf2c3d4bc4e901d0 --- /dev/null +++ b/VirtualFluidsCore/Grid/Block3D.cpp @@ -0,0 +1,532 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Block3D.cpp +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#include "Block3D.h" + +#include "Grid3DSystem.h" +#include "Block3DConnector.h" +#include "LBMKernel.h" + + +int Block3D::counter = 0; +////////////////////////////////////////////////////////////////////////// +Block3D::Block3D() : x1(0),x2(0),x3(0) + ,active(true) + ,globalID(-1) + ,rank(-1),part(-1) + ,interpolationFlagCF(0) + ,interpolationFlagFC(0) + ,level(-1) + ,bundle(-1) + ,lrank(-1) + ,localID(-1) +{ +} +////////////////////////////////////////////////////////////////////////// +Block3D::Block3D(int x1, int x2, int x3, int level) + : x1(x1), x2(x2), x3(x3) + ,active(true) + ,globalID(-1) + ,rank(0),part(0) + ,interpolationFlagCF(0) + ,interpolationFlagFC(0) + ,level(level) + ,bundle(0) + ,lrank(-1) + ,localID(-1) +{ + globalID = counter++; +} +////////////////////////////////////////////////////////////////////////// +Block3D::~Block3D() +{ +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::operator==(const Block3D& src) const +{ + return (x1==src.x1 && x2==src.x2 && x3==src.x3); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::operator!=(const Block3D& src) const +{ + return !(*this==src); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getX1() const +{ + return this->x1; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getX2() const +{ + return this->x2; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getX3() const +{ + return this->x3; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setActive(bool active) +{ + this->active = active; +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::isActive() const +{ + return this->active; +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::isNotActive() const +{ + return(!this->active); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setKernel(SPtr<LBMKernel> kernel) +{ + this->kernel = kernel; +} +////////////////////////////////////////////////////////////////////////// +SPtr<ILBMKernel> Block3D::getKernel() const +{ + return this->kernel; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::deleteKernel() +{ + this->kernel = SPtr<LBMKernel>(); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getBundle() const +{ + return bundle; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setBundle(int bundle) +{ + this->bundle = bundle; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setRank(int rank) +{ + this->rank = rank; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getRank() const +{ + return this->rank; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setLocalRank(int rank) +{ + this->lrank = rank; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getLocalRank() const +{ + return this->lrank; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getGlobalID() const +{ + return this->globalID; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setGlobalID(int id) +{ + this->globalID = id; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getLocalID() const +{ + return this->localID; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setLocalID(int id) +{ + this->localID = id; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getPart() const +{ + return this->part; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setPart(int part) +{ + this->part = part; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getLevel() const +{ + return this->level; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setLevel(int level) +{ + this->level = level; +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3DConnector> Block3D::getConnector(int dir) const +{ + for(SPtr<Block3DConnector> c : connectors) + { + if( c ) + { + if(c->getSendDir() == dir) return c; + } + } + return SPtr<Block3DConnector>(); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setConnector(SPtr<Block3DConnector> connector) +{ + connectors.push_back(connector); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::deleteConnectors() +{ + connectors.clear(); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasConnectors() +{ + for(SPtr<Block3DConnector> c : connectors) + if( c ) return true; + + return false; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackSameLevelConnectors( std::vector<SPtr<Block3DConnector>>& localSameLevelConnectors + , std::vector<SPtr<Block3DConnector>>& remoteSameLevelConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) + localSameLevelConnectors.push_back(this->connectors[i]); + else + remoteSameLevelConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackLocalSameLevelConnectors( std::vector<SPtr<Block3DConnector>>& localSameLevelConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) + localSameLevelConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackLocalSameLevelConnectors( std::vector<SPtr<Block3DConnector>>& localSameLevelConnectors, const int& dir) +{ + SPtr<Block3DConnector> connector = this->connectors[dir]; + if( this->connectors[dir] ) + { + if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) + localSameLevelConnectors.push_back(this->connectors[dir]); + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackRemoteSameLevelConnectors( std::vector<SPtr<Block3DConnector>>& remoteSameLevelConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isRemoteConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) + remoteSameLevelConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackRemoteSameLevelConnectors( std::vector<SPtr<Block3DConnector>>& remoteSameLevelConnectors, const int& dir ) +{ + SPtr<Block3DConnector> connector = this->connectors[dir]; + if( this->connectors[dir] ) + { + if( connector->isRemoteConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) + remoteSameLevelConnectors.push_back(this->connectors[dir]); + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackLocalInterpolationConnectorsCF( std::vector<SPtr<Block3DConnector>>& localInterpolationConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isLocalConnector() && connector->isInterpolationConnectorCF() ) + localInterpolationConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackRemoteInterpolationConnectorsCF( std::vector<SPtr<Block3DConnector>>& remoteInterpolationConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isRemoteConnector() && connector->isInterpolationConnectorCF() ) + remoteInterpolationConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackLocalInterpolationConnectorsFC( std::vector<SPtr<Block3DConnector>>& localInterpolationConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isLocalConnector() && connector->isInterpolationConnectorFC() ) + localInterpolationConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::pushBackRemoteInterpolationConnectorsFC( std::vector<SPtr<Block3DConnector>>& remoteInterpolationConnectors ) +{ + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isRemoteConnector() && connector->isInterpolationConnectorFC() ) + remoteInterpolationConnectors.push_back(this->connectors[i]); + } + } +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getNumberOfLocalConnectors() +{ + int count = 0; + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isLocalConnector() ) count++; + } + } + return count; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getNumberOfRemoteConnectors() +{ + int count = 0; + for(int i=0; i<(int)connectors.size(); i++) + { + SPtr<Block3DConnector> connector = this->connectors[i]; + if( this->connectors[i] ) + { + if( connector->isRemoteConnector() ) count++; + } + } + return count; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getNumberOfLocalConnectorsForSurfaces() +{ + int count = 0; + + if(connectors.size() < 6) + return count; + + for(int dir=0; dir<=5; dir++) //Hard coding. It works if you have 0...5 for E, N ... B + { + SPtr<Block3DConnector> connector = this->connectors[dir]; + if( this->connectors[dir] ) + { + if( connector->isLocalConnector() ) count++; + } + } + return count; +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getNumberOfRemoteConnectorsForSurfaces() +{ + int count = 0; + for(int dir=0; dir<=5; dir++) //Hard coding. It works if you have 0...5 for E, N ... B + { + SPtr<Block3DConnector> connector = this->connectors[dir]; + if( this->connectors[dir] ) + { + if( connector->isRemoteConnector() ) count++; + } + } + return count; +} +void Block3D::setCollectionOfInterpolationFlagCF(int flags) +{ + interpolationFlagCF = flags; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setInterpolationFlagCF(int dir) +{ + UbSystem::setBit(interpolationFlagCF, 1<<dir); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getCollectionOfInterpolationFlagCF() +{ + return interpolationFlagCF; +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlagCF(int dir) +{ + return UbSystem::bitCheck( interpolationFlagCF, 1<<dir ); +} +void Block3D::setCollectionOfInterpolationFlagFC(int flags) +{ + interpolationFlagFC = flags; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setInterpolationFlagFC(int dir) +{ + UbSystem::setBit(interpolationFlagFC, 1<<dir); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getCollectionOfInterpolationFlagFC() +{ + return interpolationFlagFC; +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlagFC(int dir) +{ + return UbSystem::bitCheck( interpolationFlagFC, 1<<dir ); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlag() +{ + return(interpolationFlagCF!=0 || interpolationFlagFC!=0); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlag(int direction) +{ + return(hasInterpolationFlagCF(direction) || hasInterpolationFlagFC(direction)); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlagCF() +{ + return(interpolationFlagCF!=0); +} +////////////////////////////////////////////////////////////////////////// +bool Block3D::hasInterpolationFlagFC() +{ + return(interpolationFlagFC!=0); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::deleteInterpolationFlag() +{ + interpolationFlagFC = 0; + interpolationFlagCF = 0; +} +////////////////////////////////////////////////////////////////////////// +std::string Block3D::toString() +{ + std::stringstream ss; + ss<<"Block3D[(x1,x2,x3,level),"; + ss<<" ("<<this->x1<<", "<<this->x2<<", "<<this->x3<<", "<<this->level<<"), id=" << globalID; + ss<< ", active="<<this->active<< ", bundle="<<this->bundle<< ", rank="<<this->rank<<"]"; + ss<<" connectors:"; + for(std::size_t i=0; i<connectors.size(); i++) + if( connectors[i] ) + { + if(connectors[i]->isLocalConnector()) + ss <<"l."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", "; + if(connectors[i]->isRemoteConnector()) + ss <<"r."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", "; + if(connectors[i]->isInterpolationConnectorCF()) + ss <<"cf."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", "; + if(connectors[i]->isInterpolationConnectorFC()) + ss <<"fc."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", "; + } + return ss.str(); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::setWeight( int rank, int weight ) +{ + std::map<int, int>::iterator it; + if((it = this->weight.find(rank)) != this->weight.end()) + it->second = weight; + else + this->weight.insert(std::make_pair(rank, weight)); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getWeight( int rank ) +{ + std::map<int, int>::iterator it; + if((it = this->weight.find(rank)) != this->weight.end()) + return it->second; + else + return 0; +} +////////////////////////////////////////////////////////////////////////// +void Block3D::addWeight( int rank, int weight ) +{ + int weight_old = getWeight(rank); + weight += weight_old; + setWeight(rank, weight); +} +////////////////////////////////////////////////////////////////////////// +void Block3D::addWeightForAll( int weight ) +{ + typedef std::map<int, int> wMap; + for (wMap::value_type &w : this->weight) + { + w.second += weight; + } +} +////////////////////////////////////////////////////////////////////////// +void Block3D::clearWeight() +{ + this->weight.clear(); +} +////////////////////////////////////////////////////////////////////////// +int Block3D::getWeightSize() +{ + return static_cast<int>(this->weight.size()); +} diff --git a/VirtualFluidsCore/Grid/Block3D.h b/VirtualFluidsCore/Grid/Block3D.h new file mode 100644 index 0000000000000000000000000000000000000000..a47c0c9df5e66d23292abee4bc4dc13b37c86d8b --- /dev/null +++ b/VirtualFluidsCore/Grid/Block3D.h @@ -0,0 +1,165 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Block3D.h +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BLOCK3D_H +#define BLOCK3D_H + +#include <PointerDefinitions.h> +#include <vector> +#include <map> +#include <string> + +class Block3DConnector; +class LBMKernel; +class ILBMKernel; + +//! A class implements a block structure +class Block3D +{ +public: + Block3D(); + Block3D(int x1, int x2, int x3, int level); + virtual ~Block3D(); + bool operator==(const Block3D& src) const; + bool operator!=(const Block3D& src) const; + + int getX1() const; + int getX2() const; + int getX3() const; + + void setActive(bool active); + bool isActive() const; + bool isNotActive() const; + + void setKernel(SPtr<LBMKernel> kernel); + SPtr<ILBMKernel> getKernel() const; + void deleteKernel(); + + void setBundle(int bundle); + int getBundle() const; + + void setRank(int rank); + int getRank() const; + + void setLocalRank(int rank); + int getLocalRank() const; + + int getGlobalID() const; + void setGlobalID(int id); + + int getLocalID() const; + void setLocalID(int id); + + int getPart() const; + void setPart(int part); + + int getLevel() const; + void setLevel(int level); + + //Connector-Section + void setConnector(SPtr<Block3DConnector> connector); + SPtr<Block3DConnector> getConnector(int dir) const; + bool hasConnectors(); + void deleteConnectors(); + void pushBackSameLevelConnectors( std::vector<SPtr<Block3DConnector> >& localSameLevelConnectors + , std::vector<SPtr<Block3DConnector> >& remoteSameLevelConnectors ); + void pushBackLocalSameLevelConnectors( std::vector<SPtr<Block3DConnector> >& localSameLevelConnectors ); + void pushBackRemoteSameLevelConnectors( std::vector<SPtr<Block3DConnector> >& remoteSameLevelConnectors ); + void pushBackLocalInterpolationConnectorsCF( std::vector<SPtr<Block3DConnector> >& localInterpolationConnectors ); + void pushBackRemoteInterpolationConnectorsCF( std::vector<SPtr<Block3DConnector> >& remoteInterpolationConnectors ); + void pushBackLocalInterpolationConnectorsFC( std::vector<SPtr<Block3DConnector> >& localInterpolationConnectors ); + void pushBackRemoteInterpolationConnectorsFC( std::vector<SPtr<Block3DConnector> >& remoteInterpolationConnectors ); + void pushBackLocalSameLevelConnectors( std::vector<SPtr<Block3DConnector> >& localSameLevelConnectors, const int& dir); + void pushBackRemoteSameLevelConnectors( std::vector<SPtr<Block3DConnector> >& remoteSameLevelConnectors, const int& dir ); + int getNumberOfLocalConnectors(); + int getNumberOfRemoteConnectors(); + int getNumberOfLocalConnectorsForSurfaces(); + int getNumberOfRemoteConnectorsForSurfaces(); + + void setWeight(int rank, int weight); + int getWeight(int rank); + void addWeightForAll(int weight); + void addWeight(int rank, int weight); + void clearWeight(); + int getWeightSize(); + + //interpolation + bool hasInterpolationFlag(); + bool hasInterpolationFlag(int dir); + void deleteInterpolationFlag(); + + int getCollectionOfInterpolationFlagCF(); + void setCollectionOfInterpolationFlagCF(int flags); + + void setInterpolationFlagCF(int dir); + bool hasInterpolationFlagCF(int dir); + bool hasInterpolationFlagCF(); + + int getCollectionOfInterpolationFlagFC(); + void setCollectionOfInterpolationFlagFC(int flags); + + void setInterpolationFlagFC(int dir); + bool hasInterpolationFlagFC(int dir); + bool hasInterpolationFlagFC(); + + std::string toString() ; + + static int getMaxGlobalID() { return counter; } + static void setMaxGlobalID(int c) { counter = 0; } + +private: + int x1; + int x2; + int x3; + + bool active; + + int interpolationFlagCF; + int interpolationFlagFC; + + SPtr<LBMKernel> kernel; + std::vector<SPtr<Block3DConnector> > connectors; + std::map<int, int> weight; + + int bundle; + int rank; + int lrank; + int globalID; + int localID; + int part; + int level; + static int counter; + +}; + +#endif //BLOCK3D_H diff --git a/VirtualFluidsCore/Grid/CMakePackage.txt b/VirtualFluidsCore/Grid/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Grid/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Grid/Calculator.cpp b/VirtualFluidsCore/Grid/Calculator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdd85a797731ceb51532ef4e43fb23c4e46f0f94 --- /dev/null +++ b/VirtualFluidsCore/Grid/Calculator.cpp @@ -0,0 +1,248 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Calculator.cpp +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#include "Calculator.h" + +#include "Grid3D.h" +#include "Block3DConnector.h" +#include "Block3D.h" +#include "UbScheduler.h" +#include "CoProcessor.h" + +#include <basics/utilities/UbException.h> + +Calculator::Calculator(SPtr<Grid3D> grid, SPtr<UbScheduler> additionalGhostLayerUpdateScheduler, int numberOfTimeSteps) : + grid(grid), + additionalGhostLayerUpdateScheduler(additionalGhostLayerUpdateScheduler), + numberOfTimeSteps(numberOfTimeSteps) +{ + this->grid = grid; + startTimeStep = int(grid->getTimeStep())+1; + minLevel = grid->getCoarsestInitializedLevel(); + maxLevel = grid->getFinestInitializedLevel(); + if (maxLevel > 0) + refinement = true; + else + refinement = false; + blocks.resize(maxLevel+1); + localConns.resize(maxLevel+1); + remoteConns.resize(maxLevel+1); + localInterConns.resize(maxLevel); + remoteInterConns.resize(maxLevel); + + int gridRank = grid->getRank(); + + for (int level = minLevel; level <= maxLevel; level++) + { + std::vector<SPtr<Block3D>> blockVector; + grid->getBlocks(level, gridRank, true, blockVector); + for (SPtr<Block3D> const block : blockVector) + if (block) + blocks[block->getLevel()].push_back(block); + } + + initLocalConnectors(); + initRemoteConnectors(); +} +////////////////////////////////////////////////////////////////////////// +Calculator::~Calculator() +{ + +} +////////////////////////////////////////////////////////////////////////// +void Calculator::addCoProcessor(SPtr<CoProcessor> coProcessor) +{ + coProcessors.push_back(coProcessor); +} +////////////////////////////////////////////////////////////////////////// +void Calculator::coProcess(double step) +{ + for (SPtr<CoProcessor> cp : coProcessors) + { + cp->process(step); + } +} +////////////////////////////////////////////////////////////////////////// +void Calculator::initLocalConnectors() +{ + UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - start"); + + for (int l = minLevel; l <= maxLevel; l++) + { + for(SPtr<Block3D> block : blocks[l]) + { + block->pushBackLocalSameLevelConnectors(localConns[l]); + + if (l != maxLevel) + block->pushBackLocalInterpolationConnectorsCF(localInterConns[l]); + } + if (l != maxLevel) + { + for(SPtr<Block3D> block : blocks[l+1]) + { + block->pushBackLocalInterpolationConnectorsFC(localInterConns[l]); + } + } + UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localConns["<<l<<"])"); + initConnectors(localConns[l]); + + if (l != maxLevel) + { + UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localInterConns["<<l<<"])"); + initConnectors(localInterConns[l]); + } + } + + UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - end"); +} +////////////////////////////////////////////////////////////////////////// +void Calculator::initRemoteConnectors() +{ + std::vector< std::vector< SPtr<Block3DConnector> > > remoteInterConnsCF; + std::vector< std::vector< SPtr<Block3DConnector> > > remoteInterConnsFC; + remoteInterConnsCF.resize(maxLevel+1); + remoteInterConnsFC.resize(maxLevel+1); + + for(int l = minLevel; l<=maxLevel;l++) + { + std::vector<SPtr<Block3D>> blockVector; + //grid->getBlocks(level, gridRank, true, blockVector); + grid->getBlocks(l, blockVector); + for(SPtr<Block3D> block : blockVector) + { + int l = block->getLevel(); + block->pushBackRemoteSameLevelConnectors(remoteConns[l]); + + block->pushBackRemoteInterpolationConnectorsCF(remoteInterConnsCF[l]); + block->pushBackRemoteInterpolationConnectorsFC(remoteInterConnsFC[l]); + } + } + + for (int l = minLevel; l <= maxLevel; l++) + { + UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteConns["<<l<<"])"); + initConnectors(remoteConns[l]); + if (l != maxLevel) + { + for(int i = 0; i < remoteInterConnsCF[l].size(); i++) + remoteInterConns[l].push_back(remoteInterConnsCF[l][i]); + for(int i = 0; i < remoteInterConnsFC[l+1].size(); i++) + remoteInterConns[l].push_back(remoteInterConnsFC[l+1][i]); + } + } + ////////////////////////////////////////////////////////////////////////// + //UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - start"); + for (int l = minLevel; l <= maxLevel; l++) + { + if (l != maxLevel) + { + UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"])"); + for(SPtr<Block3DConnector> c : remoteInterConns[l] ) c->init(); + } + } + //UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - end"); + ////////////////////////////////////////////////////////////////////////// + //sendTransmitterDataSize + //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start"); + for (int l = minLevel; l <= maxLevel; l++) + { + if (l != maxLevel) + { + UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-sendTransmitterDataSize(remoteInterConns["<<l<<"])"); + for(SPtr<Block3DConnector> c : remoteInterConns[l] ) c->sendTransmitterDataSize(); + } + } + //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end"); + ////////////////////////////////////////////////////////////////////////// + //receiveTransmitterDataSize + //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!! + //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start"); + for (int l = minLevel; l <= maxLevel; l++) + { + if (l != maxLevel) + { + UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-receiveTransmitterDataSize(remoteInterConns["<<l<<"])"); + for(SPtr<Block3DConnector> c : remoteInterConns[l] ) c->receiveTransmitterDataSize(); + } + } + //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end"); + ////////////////////////////////////////////////////////////////////////// +} +////////////////////////////////////////////////////////////////////////// +void Calculator::initConnectors(std::vector<SPtr<Block3DConnector>>& connectors) +{ + UBLOG(logDEBUG1, "Calculator::initConnectors() - start"); + + //initialization + ////////////////////////////////////////////////////////////////////////// + //initialize connectors + UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - start"); + for(SPtr<Block3DConnector> c : connectors ) c->init(); + UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - end"); + ////////////////////////////////////////////////////////////////////////// + //sendTransmitterDataSize + UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start"); + for(SPtr<Block3DConnector> c : connectors ) c->sendTransmitterDataSize(); + UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end"); + ////////////////////////////////////////////////////////////////////////// + //receiveTransmitterDataSize + //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!! + UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start"); + for(SPtr<Block3DConnector> c : connectors ) c->receiveTransmitterDataSize(); + UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end"); + + UBLOG(logDEBUG1, "Calculator::initConnectors() - end"); +} +////////////////////////////////////////////////////////////////////////// +void Calculator::deleteBlocks() +{ + for(std::vector< SPtr<Block3D> > &bs : blocks) + bs.resize(0); +} +////////////////////////////////////////////////////////////////////////// +void Calculator::deleteConnectors() +{ + deleteConnectors(localConns); + deleteConnectors(remoteConns); + + deleteConnectors(localInterConns); + deleteConnectors(remoteInterConns); +} +////////////////////////////////////////////////////////////////////////// +void Calculator::deleteConnectors(std::vector< std::vector< SPtr<Block3DConnector> > >& conns) +{ + for(std::vector< SPtr<Block3DConnector> > &c : conns) + c.resize(0); +} +////////////////////////////////////////////////////////////////////////// + diff --git a/VirtualFluidsCore/Grid/Calculator.h b/VirtualFluidsCore/Grid/Calculator.h new file mode 100644 index 0000000000000000000000000000000000000000..7816bdc587303ba81309f6cecf07857747079314 --- /dev/null +++ b/VirtualFluidsCore/Grid/Calculator.h @@ -0,0 +1,90 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Calculator.h +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef CALCULATOR_H +#define CALCULATOR_H + +#include <PointerDefinitions.h> +#include <vector> + +class Grid3D; +class UbScheduler; +class Block3D; +class Block3DConnector; +class CoProcessor; + +//! \class Calculator +//! \brief A base class for main calculation loop + +class Calculator +{ +public: + Calculator(SPtr<Grid3D> grid, SPtr<UbScheduler> additionalGhostLayerUpdateScheduler, int numberOfTimeSteps); + virtual ~Calculator(); + //! control of coProcessors + void addCoProcessor(SPtr<CoProcessor> coProcessor); + void coProcess(double step); + + virtual void calculate()=0; +protected: + virtual void initLocalConnectors(); + virtual void initRemoteConnectors(); + void initConnectors(std::vector<SPtr<Block3DConnector> >& connectors); + void deleteBlocks(); + void deleteConnectors(); + void deleteConnectors(std::vector< std::vector< SPtr<Block3DConnector> > >& conns); + + int minLevel, maxLevel; + int startTimeStep; + int numberOfTimeSteps; + std::vector< std::vector< SPtr<Block3DConnector> > > localConns; + std::vector< std::vector< SPtr<Block3DConnector> > > remoteConns; + + bool refinement; + SPtr<Grid3D> grid; + SPtr<UbScheduler> additionalGhostLayerUpdateScheduler; + std::vector< std::vector<SPtr<Block3D> > > blocks; + + //localInterConns and remoteInterConns save interpolation connectors + //every element save CF connectors for current level and FC connectors for next level + //e.g. + //localInterConns[0] = CF(0), FC(1) + //localInterConns[1] = CF(1), FC(2) + //localInterConns[2] + std::vector< std::vector< SPtr<Block3DConnector> > > localInterConns; + std::vector< std::vector< SPtr<Block3DConnector> > > remoteInterConns; + + std::vector< SPtr<CoProcessor> > coProcessors; +}; + +#endif diff --git a/VirtualFluidsCore/Grid/Grid3D.cpp b/VirtualFluidsCore/Grid/Grid3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e62153933173d3fec14fdd70e7b1378c587316ff --- /dev/null +++ b/VirtualFluidsCore/Grid/Grid3D.cpp @@ -0,0 +1,2039 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Grid.cpp +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#include "Grid3D.h" + +#include <set> + +#include <geometry3d/CoordinateTransformation3D.h> +#include <basics/writer/WbWriterVtkXmlASCII.h> + +#include "Grid3DVisitor.h" +#include "Block3DVisitor.h" +#include "Interactor3D.h" +#include "Grid3DSystem.h" +#include "LBMSystem.h" +#include <Block3D.h> +#include <Communicator.h> + + +using namespace std; + +Grid3D::Grid3D() : + rank(0), + bundle(0), + orgDeltaX(1.0), + periodicX1(false), + periodicX2(false), + periodicX3(false), + timeStep(0.0), + blockNx1(0), + blockNx2(0), + blockNx3(0), + nx1(0), + nx2(0), + nx3(0) +{ + levelSet.resize(Grid3DSystem::MAXLEVEL+1); +} +////////////////////////////////////////////////////////////////////////// +Grid3D::Grid3D(SPtr<Communicator> comm) : + rank(0), + bundle(0), + orgDeltaX(1.0), + periodicX1(false), + periodicX2(false), + periodicX3(false), + timeStep(0.0), + blockNx1(0), + blockNx2(0), + blockNx3(0), + nx1(0), + nx2(0), + nx3(0) +{ + levelSet.resize(Grid3DSystem::MAXLEVEL+1); + rank = comm->getProcessID(); +} +////////////////////////////////////////////////////////////////////////// +Grid3D::Grid3D(SPtr<Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3) : + rank(0), + bundle(0), + orgDeltaX(1.0), + periodicX1(false), + periodicX2(false), + periodicX3(false), + timeStep(0.0), + blockNx1(blockNx1), + blockNx2(blockNx2), + blockNx3(blockNx2), + nx1(gridNx1), + nx2(gridNx2), + nx3(gridNx3) +{ + levelSet.resize(Grid3DSystem::MAXLEVEL+1); + rank = comm->getProcessID(); + trafo = SPtr<CoordinateTransformation3D>(new CoordinateTransformation3D(0.0, 0.0, 0.0, (double)blockNx1, (double)blockNx2, (double)blockNx3)); + UbTupleInt3 minInd(0, 0, 0); + UbTupleInt3 maxInd(gridNx1, gridNx2, gridNx3); + this->fillExtentWithBlocks(minInd, maxInd); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::addInteractor(SPtr<Interactor3D> interactor) +{ + interactors.push_back(interactor); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::addAndInitInteractor(SPtr<Interactor3D> interactor, double timestep) +{ + interactors.push_back(interactor); + interactor->initInteractor(timestep); +} +////////////////////////////////////////////////////////////////////////// +Grid3D::Interactor3DSet Grid3D::getInteractors() +{ + return interactors; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::accept(Block3DVisitor& blockVisitor) +{ + int startLevel = blockVisitor.getStartLevel(); + int stopLevel = blockVisitor.getStopLevel(); + + if (startLevel < 0 || stopLevel < 0 || startLevel > Grid3DSystem::MAXLEVEL || stopLevel > Grid3DSystem::MAXLEVEL) + throw UbException(UB_EXARGS, "not valid level!"); + + bool dir = startLevel < stopLevel; + if (dir) stopLevel += 1; + else stopLevel -= 1; + +//#pragma omp parallel +// { +// for (int l = startLevel; l!=stopLevel;) +// { +// std::vector<SPtr<Block3D>> blockVector; +// getBlocks(l, blockVector); +// int sizeb = (int)blockVector.size(); +// +//#pragma omp for +// for (int i = 0; i < sizeb; i++) +// { +// blockVisitor.visit(shared_from_this(), blockVector[i]); +// } +// if (dir) l++; +// else l--; +// } +// } + for(int l=startLevel; l!=stopLevel;) + { + std::vector<SPtr<Block3D>> blockVector; + getBlocks(l, blockVector); + for(SPtr<Block3D> b : blockVector) + { + blockVisitor.visit( shared_from_this(), b ); + } + if(dir) l++; + else l--; + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::accept(Grid3DVisitor& gridVisitor) +{ + gridVisitor.visit(shared_from_this()); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::accept(SPtr<Grid3DVisitor> gridVisitor) +{ + gridVisitor->visit(shared_from_this()); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::addBlock(SPtr<Block3D> block) +{ + if (block) + { + this->blockIdMap.insert(std::make_pair(block->getGlobalID(), block)); + int level = block->getLevel(); + this->levelSet[level].insert(std::make_pair(Block3DKey(block->getX1(), block->getX2(), block->getX3()), block)).second; + } +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::deleteBlock(SPtr<Block3D> block) +{ + return this->deleteBlock(block->getX1(), block->getX2(), block->getX3(), block->getLevel()); +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::deleteBlock(int ix1, int ix2, int ix3, int level) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2, ix3, level); + if (block) + { + this->blockIdMap.erase(block->getGlobalID()); + return this->levelSet[level].erase(Block3DKey(ix1, ix2, ix3)) > 0; + } + else + { + return false; + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::replaceBlock(SPtr<Block3D> block) +{ + if (block) + { + this->deleteBlock(block); + this->addBlock(block); + } +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::getBlock(int ix1, int ix2, int ix3, int level) const +{ + if (!this->hasLevel(level)) return SPtr<Block3D>(); + + int N1 = (nx1<<level); + int N2 = (nx2<<level); + int N3 = (nx3<<level); + + if (!this->isPeriodicX1() && (ix1>N1-1 || ix1<0)) return SPtr<Block3D>(); + else if (this->isPeriodicX1() && (ix1>=N1-1 || ix1<0)) { ix1=((ix1%N1)+N1)%N1; } + if (!this->isPeriodicX2() && (ix2>N2-1 || ix2<0)) return SPtr<Block3D>(); + else if (this->isPeriodicX2() && (ix2>=N2-1 || ix2<0)) { ix2=((ix2%N2)+N2)%N2; } + if (!this->isPeriodicX3() && (ix3>N3-1 || ix3<0)) return SPtr<Block3D>(); + else if (this->isPeriodicX3() && (ix3>=N3-1 || ix3<0)) { ix3=((ix3%N3)+N3)%N3; } + + Block3DMap::const_iterator it; + it = levelSet[level].find(Block3DKey(ix1, ix2, ix3)); + if (it == levelSet[level].end()) + return SPtr<Block3D>(); + else + return it->second; +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::getBlock(int id) const +{ + BlockIDMap::const_iterator it; + if ((it=blockIdMap.find(id)) == blockIdMap.end()) + { + return SPtr<Block3D>(); + } + + return it->second; +} +////////////////////////////////////////////////////////////////////////// +Grid3D::BlockIDMap& Grid3D::getBlockIDs() +{ + return blockIdMap; +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::getSuperBlock(SPtr<Block3D> block) +{ + int ix1 = block->getX1(); + int ix2 = block->getX2(); + int ix3 = block->getX3(); + int level = block->getLevel(); + return getSuperBlock(ix1, ix2, ix3, level); +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::getSuperBlock(int ix1, int ix2, int ix3, int level) +{ + if (!this->hasLevel(level)) return SPtr<Block3D>(); + if (level < 1) throw UbException(UB_EXARGS, "level <1"); + + //from Lower Level to higher: >> 1 in x1,x2,x3 + SPtr<Block3D> block; + for (int l=level-1; l>=0; l--) + { + ix1 = ix1 >> 1; + ix2 = ix2 >> 1; + ix3 = ix3 >> 1; + + block = this->getBlock(ix1, ix2, ix3, l); + if (block) return block; + } + return SPtr<Block3D>(); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocks(SPtr<Block3D> block, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + int ix1 = block->getX1(); + int ix2 = block->getX2(); + int ix3 = block->getX3(); + int level = block->getLevel(); + getSubBlocks(ix1, ix2, ix3, level, levelDepth, blocks); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocks(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + if (!this->getBlock(ix1, ix2, ix3, level)) return; + if (level > 0 && !this->getSuperBlock(ix1, ix2, ix3, level)) return; + if (level >= Grid3DSystem::MAXLEVEL) throw UbException(UB_EXARGS, "Level bigger then MAXLEVEL"); + + int x1[] ={ ix1<<1, (ix1<<1)+1 }; + int x2[] ={ ix2<<1, (ix2<<1)+1 }; + int x3[] ={ ix3<<1, (ix3<<1)+1 }; + int l = level + 1; + + for (int i=0; i<2; i++) + for (int j=0; j<2; j++) + for (int k=0; k<2; k++) + { + SPtr<Block3D> block = this->getBlock(x1[i], x2[j], x3[k], l); + if (block) blocks.push_back(block); + else if (l < levelDepth) this->getSubBlocks(x1[i], x2[j], x3[k], l, levelDepth, blocks); + } +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::expandBlock(int ix1, int ix2, int ix3, int level) +{ + this->checkLevel(level); + + SPtr<Block3D> block = this->getBlock(ix1, ix2, ix3, level); + if (!block) throw UbException(UB_EXARGS, "block(x1="+UbSystem::toString(ix1)+", x2="+UbSystem::toString(ix2)+", x3="+UbSystem::toString(ix3)+", l="+UbSystem::toString(level)+") is not exist"); + + //da bei periodic der eigentliche block andere indizes hat: + ix1 = block->getX1(); + ix2 = block->getX2(); + ix3 = block->getX3(); + + int l = level+1; + if (l>Grid3DSystem::MAXLEVEL) throw UbException(UB_EXARGS, "level > Grid3D::MAXLEVEL"); + + int west = ix1<<1; + int east = west+1; + int south = ix2<<1; + int north = south+1; + int bottom = ix3<<1; + int top = bottom+1; + + SPtr<Block3D> blockBSW = SPtr<Block3D>(new Block3D(west, south, bottom, l)); + SPtr<Block3D> blockBSE = SPtr<Block3D>(new Block3D(east, south, bottom, l)); + SPtr<Block3D> blockBNW = SPtr<Block3D>(new Block3D(west, north, bottom, l)); + SPtr<Block3D> blockBNE = SPtr<Block3D>(new Block3D(east, north, bottom, l)); + SPtr<Block3D> blockTSW = SPtr<Block3D>(new Block3D(west, south, top, l)); + SPtr<Block3D> blockTSE = SPtr<Block3D>(new Block3D(east, south, top, l)); + SPtr<Block3D> blockTNW = SPtr<Block3D>(new Block3D(west, north, top, l)); + SPtr<Block3D> blockTNE = SPtr<Block3D>(new Block3D(east, north, top, l)); + + if (!this->deleteBlock(ix1, ix2, ix3, level)) + throw UbException(UB_EXARGS, "could not delete block"); + + this->addBlock(blockBSW); + this->addBlock(blockBSE); + this->addBlock(blockBNW); + this->addBlock(blockBNE); + this->addBlock(blockTSW); + this->addBlock(blockTSE); + this->addBlock(blockTNW); + this->addBlock(blockTNE); + + return true; +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::collapseBlock(int fix1, int fix2, int fix3, int flevel, int levelDepth) +{ + using UbSystem::toString; + + SPtr<Block3D> fblock = this->getBlock(fix1, fix2, fix3, flevel); + if (flevel < 1) throw UbException(UB_EXARGS, "level of block ("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") is < 1"); + if (!fblock) + { + throw UbException(UB_EXARGS, "specific block("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") doesn't exists"); + } + if (!fblock->isActive()) throw UbException(UB_EXARGS, "block("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") is not active"); + + //da bei periodic der eigentliche block andere indizes hat: + fix1 = fblock->getX1(); + fix2 = fblock->getX2(); + fix3 = fblock->getX3(); + + int cix1 = fblock->getX1() >> 1; + int cix2 = fblock->getX2() >> 1; + int cix3 = fblock->getX3() >> 1; + + int fx1[2] ={ cix1<<1, (cix1<<1)+1 }; + int fx2[2] ={ cix2<<1, (cix2<<1)+1 }; + int fx3[2] ={ cix3<<1, (cix3<<1)+1 }; + int clevel = flevel - 1; + + vector<SPtr<Block3D>> blocks; + for (int i=0; i<2; i++) + for (int k=0; k<2; k++) + for (int l=0; l<2; l++) + { + this->getSubBlocks(fx1[k], fx2[i], fx3[l], flevel, levelDepth, blocks); + while (!blocks.empty()) + { + //man muss nur eine von den moeglichen acht "collapsen", die anderen werden + //dann (rekursiv) collapsed, da die schleife oben alle vier abfragt + this->collapseBlock(blocks[0]->getX1(), blocks[0]->getX2(), blocks[0]->getX3(), blocks[0]->getLevel(), levelDepth); + this->getSubBlocks(fx1[k], fx2[i], fx3[l], flevel, levelDepth, blocks); + } + } + + vector<SPtr<Block3D>> fineBlocks(8); + /*BSW*/fineBlocks[0] = this->getBlock(fx1[0], fx2[0], fx3[0], flevel); + /*BSE*/fineBlocks[1] = this->getBlock(fx1[1], fx2[0], fx3[0], flevel); + /*BNE*/fineBlocks[2] = this->getBlock(fx1[1], fx2[1], fx3[0], flevel); + /*BNW*/fineBlocks[3] = this->getBlock(fx1[0], fx2[1], fx3[0], flevel); + /*TSW*/fineBlocks[4] = this->getBlock(fx1[0], fx2[0], fx3[1], flevel); + /*TSE*/fineBlocks[5] = this->getBlock(fx1[1], fx2[0], fx3[1], flevel); + /*TNE*/fineBlocks[6] = this->getBlock(fx1[1], fx2[1], fx3[1], flevel); + /*TNW*/fineBlocks[7] = this->getBlock(fx1[0], fx2[1], fx3[1], flevel); + + SPtr<Block3D> cblock = SPtr<Block3D>(new Block3D(cix1, cix2, cix3, clevel)); + + for (int i=0; i<2; i++) + for (int k=0; k<2; k++) + for (int l=0; l<2; l++) + if (!this->deleteBlock(fx1[k], fx2[i], fx3[l], flevel)) + throw UbException(UB_EXARGS, "could not delete block"); + + this->addBlock(cblock); + + return cblock; +} +////////////////////////////////////////////////////////////////////////// +// TODO: make visitor for this +void Grid3D::deleteConnectors() +{ + for (Block3DMap blockMap : levelSet) + { + for (Block3DMap::value_type b : blockMap) + { + SPtr<Block3D> block = b.second; + block->deleteConnectors(); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setRank(int rank) +{ + this->rank = rank; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getRank() const +{ + return rank; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getBundle() const +{ + return bundle; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setBundle(int bundle) +{ + this->bundle = bundle; +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::isPeriodicX1() const +{ + return this->periodicX1; +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::isPeriodicX2() const +{ + return this->periodicX2; +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::isPeriodicX3() const +{ + return this->periodicX3; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setPeriodicX1(bool value) +{ + this->periodicX1 = value; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setPeriodicX2(bool value) +{ + this->periodicX2 = value; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setPeriodicX3(bool value) +{ + this->periodicX3 = value; +} +////////////////////////////////////////////////////////////////////////// +UbTupleInt3 Grid3D::getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord) const +{ + if (!trafo) + { + return makeUbTuple((int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord); + } + + return makeUbTuple((int)trafo->transformForwardToX1Coordinate(blockX1Coord, blockX2Coord, blockX3Coord) + , (int)trafo->transformForwardToX2Coordinate(blockX1Coord, blockX2Coord, blockX3Coord) + , (int)trafo->transformForwardToX3Coordinate(blockX1Coord, blockX2Coord, blockX3Coord)); + +} +////////////////////////////////////////////////////////////////////////// +UbTupleInt3 Grid3D::getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord, int level) const +{ + if (!trafo) + { + return makeUbTuple((int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord); + } + + double dx = getDeltaX(level); + double blockLentghX1, blockLentghX2, blockLentghX3; + blockLentghX1 = blockNx1*dx; + blockLentghX2 = blockNx2*dx; + blockLentghX3 = blockNx3*dx; + UbTupleDouble3 org = getBlockWorldCoordinates(0, 0, 0, 0); + + SPtr<CoordinateTransformation3D> trafo_temp(new CoordinateTransformation3D(val<1>(org), val<2>(org), val<3>(org), blockLentghX1, blockLentghX2, blockLentghX3)); + + if (!trafo_temp) + { + return makeUbTuple((int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord); + } + + return makeUbTuple((int)trafo_temp->transformForwardToX1Coordinate(blockX1Coord, blockX2Coord, blockX3Coord) + , (int)trafo_temp->transformForwardToX2Coordinate(blockX1Coord, blockX2Coord, blockX3Coord) + , (int)trafo_temp->transformForwardToX3Coordinate(blockX1Coord, blockX2Coord, blockX3Coord)); + +} +////////////////////////////////////////////////////////////////////////// +UbTupleDouble3 Grid3D::getBlockLengths(const SPtr<Block3D> block) const +{ + int level = block->getLevel(); + double delta = 1.0/(double)(1<<level); + + if (!trafo) makeUbTuple<double, double, double>(delta, delta, delta); + + return makeUbTuple(trafo->getX1CoordinateScaling()*delta, + trafo->getX2CoordinateScaling()*delta, + trafo->getX3CoordinateScaling()*delta); +} +////////////////////////////////////////////////////////////////////////// +UbTupleDouble6 Grid3D::getBlockOversize() const +{ + return makeUbTuple(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setCoordinateTransformator(SPtr<CoordinateTransformation3D> trafo) +{ + this->trafo = trafo; +} +////////////////////////////////////////////////////////////////////////// +const SPtr<CoordinateTransformation3D> Grid3D::getCoordinateTransformator() const +{ + return this->trafo; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setDeltaX(double dx) +{ + this->orgDeltaX = dx; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setDeltaX(double worldUnit, double gridUnit) +{ + this->orgDeltaX = worldUnit/gridUnit; +} +////////////////////////////////////////////////////////////////////////// +double Grid3D::getDeltaX(int level) const +{ + double delta = this->orgDeltaX/(double)(1<<level); + return delta; +} +////////////////////////////////////////////////////////////////////////// +double Grid3D::getDeltaX(SPtr<Block3D> block) const +{ + return getDeltaX(block->getLevel()); +} +////////////////////////////////////////////////////////////////////////// +UbTupleDouble3 Grid3D::getNodeOffset(SPtr<Block3D> block) const +{ + double delta = this->getDeltaX(block); + return makeUbTuple(OFFSET * delta, OFFSET * delta, OFFSET * delta); +} +//////////////////////////////////////////////////////////////////////////// +Vector3D Grid3D::getNodeCoordinates(SPtr<Block3D> block, int ix1, int ix2, int ix3) const +{ + UbTupleDouble3 org = this->getBlockWorldCoordinates(block); + UbTupleDouble3 nodeOffset = this->getNodeOffset(block); + double deltaX = getDeltaX(block); + + double x1 = val<1>(org) - val<1>(nodeOffset) + (double)ix1*deltaX; + double x2 = val<2>(org) - val<2>(nodeOffset) + (double)ix2*deltaX; + double x3 = val<3>(org) - val<3>(nodeOffset) + (double)ix3*deltaX; + + return Vector3D(x1, x2, x3); +} +//////////////////////////////////////////////////////////////////////////// +UbTupleInt3 Grid3D::getNodeIndexes(SPtr<Block3D> block, double nodeX1Coord, double nodeX2Coord, double nodeX3Coord) const +{ + UbTupleDouble3 org = this->getBlockWorldCoordinates(block); + UbTupleDouble3 nodeOffset = this->getNodeOffset(block); + double deltaX = getDeltaX(block); + + int ix1, ix2, ix3; + double ixx1=(abs(nodeX1Coord - val<1>(org) + val<1>(nodeOffset)) / deltaX); + double ixx2=(abs(nodeX2Coord - val<2>(org) + val<2>(nodeOffset)) / deltaX); + double ixx3=(abs(nodeX3Coord - val<3>(org) + val<3>(nodeOffset)) / deltaX); + if (ixx1-(int)ixx1>.9999999999) ix1=(int)ixx1+1; else ix1=(int)ixx1; + if (ixx2-(int)ixx2>.9999999999) ix2=(int)ixx2+1; else ix2=(int)ixx2; + if (ixx3-(int)ixx3>.9999999999) ix3=(int)ixx3+1; else ix3=(int)ixx3; + + return makeUbTuple(ix1, ix2, ix3); +} +////////////////////////////////////////////////////////////////////////// +//returns tuple with origin of block in world-coordinates +UbTupleDouble3 Grid3D::getBlockWorldCoordinates(SPtr<Block3D> block) const +{ + if (!block) + throw UbException(UB_EXARGS, "block " + block->toString() + "is not exist"); + + int blockX1Index = block->getX1(); + int blockX2Index = block->getX2(); + int blockX3Index = block->getX3(); + int level = block->getLevel(); + + return this->getBlockWorldCoordinates(blockX1Index, blockX2Index, blockX3Index, level); +} +////////////////////////////////////////////////////////////////////////// +UbTupleDouble3 Grid3D::getBlockWorldCoordinates(int blockX1Index, int blockX2Index, int blockX3Index, int level) const +{ + double c1oShiftedLevel = 1.0/(double)(1<<level); + double x1 = (double)blockX1Index*c1oShiftedLevel; + double x2 = (double)blockX2Index*c1oShiftedLevel; + double x3 = (double)blockX3Index*c1oShiftedLevel; + + if (!trafo) return UbTupleDouble3(x1, x2, x3); + + return UbTupleDouble3(trafo->transformBackwardToX1Coordinate(x1, x2, x3) + , trafo->transformBackwardToX2Coordinate(x1, x2, x3) + , trafo->transformBackwardToX3Coordinate(x1, x2, x3)); +} +////////////////////////////////////////////////////////////////////////// +//double Grid3D::getDeltaT(SPtr<Block3D> block) const +//{ +// int level = block->getLevel(); +// double delta = 1.0/(double)(1<<level); +// return delta; +//} +////////////////////////////////////////////////////////////////////////// +void Grid3D::checkLevel(int level) +{ + if (level < 0) + { + throw UbException(UB_EXARGS, "l("+UbSystem::toString(level)+(string)")<0"); + } + if (level > Grid3DSystem::MAXLEVEL) + { + throw UbException(UB_EXARGS, "l("+UbSystem::toString(level)+(string)")>MAXLEVEL"); + } + if (this->levelSet[level].size() == 0) + { + throw UbException(UB_EXARGS, "levelMap for level("+UbSystem::toString(level)+(string)")==NULL"); + } +} +////////////////////////////////////////////////////////////////////////// +bool Grid3D::hasLevel(int level) const +{ + if (level < 0) return false; + if (level > Grid3DSystem::MAXLEVEL) return false; + if (this->levelSet[level].size() == 0) return false; + + return true; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setBlockNX(int nx1, int nx2, int nx3) +{ + blockNx1 = nx1; + blockNx2 = nx2; + blockNx3 = nx3; +} +////////////////////////////////////////////////////////////////////////// +UbTupleInt3 Grid3D::getBlockNX() const +{ + return makeUbTuple(blockNx1, blockNx2, blockNx3); +} +////////////////////////////////////////////////////////////////////////// + +SPtr<Block3D> Grid3D::getNeighborBlock(int dir, int ix1, int ix2, int ix3, int level) const +{ + return this->getBlock(ix1+Grid3DSystem::EX1[dir], ix2+Grid3DSystem::EX2[dir], ix3+Grid3DSystem::EX3[dir], level); +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> Grid3D::getNeighborBlock(int dir, SPtr<Block3D> block) const +{ + int x1 = block->getX1(); + int x2 = block->getX2(); + int x3 = block->getX3(); + int level = block->getLevel(); + return this->getNeighborBlock(dir, x1, x2, x3, level); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getAllNeighbors(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + for (int dir=Grid3DSystem::STARTDIR; dir<=Grid3DSystem::ENDDIR; dir++) + //for (int dir = Grid3DSystem::STARTDIR; dir<=Grid3DSystem::TS; dir++) + { + this->getNeighborBlocksForDirection(dir, ix1, ix2, ix3, level, levelDepth, blocks); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getAllNeighbors(SPtr<Block3D> block, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + int x1 = block->getX1(); + int x2 = block->getX2(); + int x3 = block->getX3(); + getAllNeighbors(x1, x2, x3, level, levelDepth, blocks); +} +////////////////////////////////////////////////////////////////////////// + /** + * Returns all direct northern neighbor cells of the specified grid cell (may be NULL!). + * @param ix1 index in x1 direction + * @param ix2 index in x2 direction + * @param ix3 index in x3 direction + * @param level the level + */ +void Grid3D::getNeighborsNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksSouth(ix1, ix2+1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTop(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottom(ix1, ix2, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottom(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + + } + this->getSubBlocksTop(ix1, ix2, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + + } + this->getSubBlocksNorth(ix1, ix2-1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksWest(ix1+1, ix2, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksEast(ix1-1, ix2, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// diagonals +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksSouthWest(ix1+1, ix2+1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2+1, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksSouthEast(ix1-1, ix2+1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksNorthWest(ix1+1, ix2-1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2-1, ix3, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksNorthEast(ix1-1, ix2-1, ix3, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// diagonals top +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomWest(ix1+1, ix2, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomEast(ix1-1, ix2, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomSouth(ix1, ix2+1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomNorth(ix1, ix2-1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// diagonals bottom +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopWest(ix1+1, ix2, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopEast(ix1-1, ix2, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopSouth(ix1, ix2+1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopNorth(ix1, ix2-1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomSouthWest(ix1+1, ix2+1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2+1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomSouthEast(ix1-1, ix2+1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomNorthWest(ix1+1, ix2-1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsTopSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2-1, ix3+1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksBottomNorthEast(ix1-1, ix2-1, ix3+1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopSouthWest(ix1+1, ix2+1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2+1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopSouthEast(ix1-1, ix2+1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1+1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1+1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopNorthWest(ix1+1, ix2-1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsBottomSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1-1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1-1, ix2-1, ix3-1, level); + if (block) { blocks.push_back(block); } + } + this->getSubBlocksTopNorthEast(ix1-1, ix2-1, ix3-1, level, blocks, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborBlocksForDirection(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + switch (dir) + { + case Grid3DSystem::E: this->getNeighborsEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::W: this->getNeighborsWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::N: this->getNeighborsNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::S: this->getNeighborsSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::T: this->getNeighborsTop(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::B: this->getNeighborsBottom(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::NE: this->getNeighborsNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::SW: this->getNeighborsSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::SE: this->getNeighborsSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::NW: this->getNeighborsNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TE: this->getNeighborsTopEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BW: this->getNeighborsBottomWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BE: this->getNeighborsBottomEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TW: this->getNeighborsTopWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TN: this->getNeighborsTopNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BS: this->getNeighborsBottomSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BN: this->getNeighborsBottomNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TS: this->getNeighborsTopSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TNE: this->getNeighborsTopNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TNW: this->getNeighborsTopNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TSE: this->getNeighborsTopSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TSW: this->getNeighborsTopSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BNE: this->getNeighborsBottomNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BNW: this->getNeighborsBottomNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BSE: this->getNeighborsBottomSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BSW: this->getNeighborsBottomSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + default:throw UbException(UB_EXARGS, "direction "+UbSystem::toString(dir)+" is not exist"); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborsZero(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + SPtr<Block3D> block = this->getBlock(ix1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + + if (level > 0) + { + block = this->getSuperBlock(ix1, ix2, ix3, level); + if (block) { blocks.push_back(block); } + } + // this->getSubBlocksNull(ix1, ix2, ix3, level, blocks, levelDepth); + this->getSubBlocks(ix1, ix2, ix3, level, levelDepth, blocks); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksZero(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1E = (ix1 << 1) + 1; + int x1W = (ix1 << 1); + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3B = ix3 << 1; + int x3T = x3B + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1E, x2S, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1E, x2S, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2N, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1E, x2N, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2S, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1E, x2S, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2N, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1E, x2N, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2S, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1W, x2S, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2N, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1W, x2N, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2S, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1W, x2S, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2N, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1W, x2N, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getNeighborBlocksForDirectionWithDirZero(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks) +{ + switch (dir) + { + case Grid3DSystem::E: this->getNeighborsEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::W: this->getNeighborsWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::N: this->getNeighborsNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::S: this->getNeighborsSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::T: this->getNeighborsTop(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::B: this->getNeighborsBottom(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::NE: this->getNeighborsNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::SW: this->getNeighborsSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::SE: this->getNeighborsSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::NW: this->getNeighborsNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TE: this->getNeighborsTopEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BW: this->getNeighborsBottomWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BE: this->getNeighborsBottomEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TW: this->getNeighborsTopWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TN: this->getNeighborsTopNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BS: this->getNeighborsBottomSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BN: this->getNeighborsBottomNorth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TS: this->getNeighborsTopSouth(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TNE: this->getNeighborsTopNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TNW: this->getNeighborsTopNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TSE: this->getNeighborsTopSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::TSW: this->getNeighborsTopSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BNE: this->getNeighborsBottomNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BNW: this->getNeighborsBottomNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BSE: this->getNeighborsBottomSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::BSW: this->getNeighborsBottomSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break; + case Grid3DSystem::REST: this->getNeighborsZero(ix1, ix2, ix3, level, levelDepth, blocks); break; + default:throw UbException(UB_EXARGS, "direction "+UbSystem::toString(dir)+" is not exist"); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksEast(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3B = ix3 << 1; + int x3T = x3B + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1, x2S, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1, x2S, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2N, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1, x2N, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2S, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1, x2S, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2N, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksEast(x1, x2N, x3T, l, blockVector, levelDepth); +} + +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksWest(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3B = ix3 << 1; + int x3T = x3B + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1, x2S, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksWest(x1, x2S, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2N, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksWest(x1, x2N, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2S, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksWest(x1, x2S, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1, x2N, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksWest(x1, x2N, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksNorth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1W = ix1 << 1; + int x1E = x1W + 1; + int x2 = (ix2 << 1) + 1; + int x3B = ix3 << 1; + int x3T = x3B + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1W, x2, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksNorth(x1W, x2, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksNorth(x1E, x2, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksNorth(x1W, x2, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksNorth(x1E, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksSouth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1W = ix1 << 1; + int x1E = x1W + 1; + int x2 = ix2 << 1; + int x3B = ix3 << 1; + int x3T = x3B + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1W, x2, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksSouth(x1W, x2, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2, x3B, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksSouth(x1E, x2, x3B, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksSouth(x1W, x2, x3T, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2, x3T, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksSouth(x1E, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTop(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1W = ix1 << 1; + int x1E = x1W + 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3 = (ix3 << 1) + 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1W, x2N, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksTop(x1W, x2N, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2N, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksTop(x1E, x2N, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2S, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksTop(x1W, x2S, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2S, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksTop(x1E, x2S, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottom(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>> &blockVector, int levelDepth) +{ + int x1W = ix1 << 1; + int x1E = x1W + 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> block = this->getBlock(x1W, x2N, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksBottom(x1W, x2N, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2N, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksBottom(x1E, x2N, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1W, x2S, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksBottom(x1W, x2S, x3, l, blockVector, levelDepth); + + block = this->getBlock(x1E, x2S, x3, l); + if (block != NULL) blockVector.push_back(block); + else if (l < levelDepth) this->getSubBlocksBottom(x1E, x2S, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// diagonals +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksNorthEast(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = (ix2 << 1) + 1; + int x3B = (ix3 << 1); + int x3T = x3B+1; + int l = level + 1; + + SPtr<Block3D> blockB = this->getBlock(x1, x2, x3B, l); + if (blockB) blockVector.push_back(blockB); + else if (l < levelDepth) this->getSubBlocksNorthEast(x1, x2, x3B, l, blockVector, levelDepth); + + SPtr<Block3D> blockT = this->getBlock(x1, x2, x3T, l); + if (blockT) blockVector.push_back(blockT); + else if (l < levelDepth) this->getSubBlocksNorthEast(x1, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksNorthWest(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1); + int x2 = (ix2 << 1) + 1; + int x3B = (ix3 << 1); + int x3T = x3B+1; + int l = level + 1; + + SPtr<Block3D> blockB = this->getBlock(x1, x2, x3B, l); + if (blockB) blockVector.push_back(blockB); + else if (l < levelDepth) this->getSubBlocksNorthWest(x1, x2, x3B, l, blockVector, levelDepth); + + SPtr<Block3D> blockT = this->getBlock(x1, x2, x3T, l); + if (blockT) blockVector.push_back(blockT); + else if (l < levelDepth) this->getSubBlocksNorthWest(x1, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksSouthWest(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2 = ix2 << 1; + int x3B = (ix3 << 1); + int x3T = x3B+1; + int l = level + 1; + + SPtr<Block3D> blockB = this->getBlock(x1, x2, x3B, l); + if (blockB) blockVector.push_back(blockB); + else if (l < levelDepth) this->getSubBlocksSouthWest(x1, x2, x3B, l, blockVector, levelDepth); + + SPtr<Block3D> blockT = this->getBlock(x1, x2, x3T, l); + if (blockT) blockVector.push_back(blockT); + else if (l < levelDepth) this->getSubBlocksSouthWest(x1, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksSouthEast(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = ix2 << 1; + int x3B = (ix3 << 1); + int x3T = x3B+1; + int l = level + 1; + + SPtr<Block3D> blockB = this->getBlock(x1, x2, x3B, l); + if (blockB) blockVector.push_back(blockB); + else if (l < levelDepth) this->getSubBlocksSouthEast(x1, x2, x3B, l, blockVector, levelDepth); + + SPtr<Block3D> blockT = this->getBlock(x1, x2, x3T, l); + if (blockT) blockVector.push_back(blockT); + else if (l < levelDepth) this->getSubBlocksSouthEast(x1, x2, x3T, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// diagonals +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopEast(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2S = (ix2 << 1); + int x2N = x2S + 1; + int x3 = (ix3 << 1)+1; + int l = level + 1; + + SPtr<Block3D> blockN = this->getBlock(x1, x2N, x3, l); + if (blockN) blockVector.push_back(blockN); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockS = this->getBlock(x1, x2S, x3, l); + if (blockS) blockVector.push_back(blockS); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopWest(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3 = (ix3 << 1)+1; + int l = level + 1; + + SPtr<Block3D> blockN = this->getBlock(x1, x2N, x3, l); + if (blockN) blockVector.push_back(blockN); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockS = this->getBlock(x1, x2S, x3, l); + if (blockS) blockVector.push_back(blockS); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomEast(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2S = ix2 << 1; + int x2N = x2S + 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockN = this->getBlock(x1, x2N, x3, l); + if (blockN) blockVector.push_back(blockN); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockS = this->getBlock(x1, x2S, x3, l); + if (blockS) blockVector.push_back(blockS); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomWest(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1); + int x2S = (ix2 << 1); + int x2N = x2S + 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockN = this->getBlock(x1, x2N, x3, l); + if (blockN) blockVector.push_back(blockN); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockS = this->getBlock(x1, x2S, x3, l); + if (blockS) blockVector.push_back(blockS); + else if (l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth); +} + +////////////////////////////////////////////////////////////////////////// +// edge-diagonals +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopNorth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1E = (ix1 << 1); + int x1W = x1E + 1; + int x2 = (ix2 << 1)+1; + int x3 = (ix3 << 1)+1; + int l = level + 1; + + SPtr<Block3D> blockE = this->getBlock(x1E, x2, x3, l); + if (blockE) blockVector.push_back(blockE); + else if (l < levelDepth) this->getSubBlocksTopNorth(x1E, x2, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockW = this->getBlock(x1W, x2, x3, l); + if (blockW) blockVector.push_back(blockW); + else if (l < levelDepth) this->getSubBlocksTopNorth(x1W, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopSouth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1E = (ix1 << 1); + int x1W = x1E + 1; + int x2 = (ix2 << 1); + int x3 = (ix3 << 1)+1; + int l = level + 1; + + SPtr<Block3D> blockE = this->getBlock(x1E, x2, x3, l); + if (blockE) blockVector.push_back(blockE); + else if (l < levelDepth) this->getSubBlocksTopSouth(x1E, x2, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockW = this->getBlock(x1W, x2, x3, l); + if (blockW) blockVector.push_back(blockW); + else if (l < levelDepth) this->getSubBlocksTopSouth(x1W, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomNorth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1E = ix1 << 1; + int x1W = x1E + 1; + int x2 = (ix2 << 1)+1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockE = this->getBlock(x1E, x2, x3, l); + if (blockE) blockVector.push_back(blockE); + else if (l < levelDepth) this->getSubBlocksBottomNorth(x1E, x2, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockW = this->getBlock(x1W, x2, x3, l); + if (blockW) blockVector.push_back(blockW); + else if (l < levelDepth) this->getSubBlocksBottomNorth(x1W, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomSouth(int ix1, int ix2, int ix3, int level, vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1E = (ix1 << 1); + int x1W = x1E + 1; + int x2 = ix2 << 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockE = this->getBlock(x1E, x2, x3, l); + if (blockE) blockVector.push_back(blockE); + else if (l < levelDepth) this->getSubBlocksBottomSouth(x1E, x2, x3, l, blockVector, levelDepth); + + SPtr<Block3D> blockW = this->getBlock(x1W, x2, x3, l); + if (blockW) blockVector.push_back(blockW); + else if (l < levelDepth) this->getSubBlocksBottomSouth(x1W, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +// space-diagonals +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopNorthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = (ix2 << 1) + 1; + int x3 = (ix3 << 1) + 1; + int l = level + 1; + + SPtr<Block3D> blockTNE = this->getBlock(x1, x2, x3, l); + if (blockTNE) blockVector.push_back(blockTNE); + else if (l < levelDepth) this->getSubBlocksTopNorthEast(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopNorthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2 = (ix2 << 1) + 1; + int x3 = (ix3 << 1) + 1; + int l = level + 1; + + SPtr<Block3D> blockTNW = this->getBlock(x1, x2, x3, l); + if (blockTNW) blockVector.push_back(blockTNW); + else if (l < levelDepth) this->getSubBlocksTopNorthWest(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopSouthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = ix2 << 1; + int x3 = (ix3 << 1) + 1; + int l = level + 1; + + SPtr<Block3D> blockTNW = this->getBlock(x1, x2, x3, l); + if (blockTNW) blockVector.push_back(blockTNW); + else if (l < levelDepth) this->getSubBlocksTopSouthEast(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksTopSouthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2 = ix2 << 1; + int x3 = (ix3 << 1) + 1; + int l = level + 1; + + SPtr<Block3D> blockTSW = this->getBlock(x1, x2, x3, l); + if (blockTSW) blockVector.push_back(blockTSW); + else if (l < levelDepth) this->getSubBlocksTopSouthWest(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomNorthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = (ix2 << 1) + 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockBNE = this->getBlock(x1, x2, x3, l); + if (blockBNE) blockVector.push_back(blockBNE); + else if (l < levelDepth) this->getSubBlocksBottomNorthEast(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomNorthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2 = (ix2 << 1) + 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockBNW = this->getBlock(x1, x2, x3, l); + if (blockBNW) blockVector.push_back(blockBNW); + else if (l < levelDepth) this->getSubBlocksBottomNorthWest(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomSouthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = (ix1 << 1) + 1; + int x2 = ix2 << 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockBSE = this->getBlock(x1, x2, x3, l); + if (blockBSE) blockVector.push_back(blockBSE); + else if (l < levelDepth) this->getSubBlocksBottomSouthEast(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getSubBlocksBottomSouthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth) +{ + int x1 = ix1 << 1; + int x2 = ix2 << 1; + int x3 = ix3 << 1; + int l = level + 1; + + SPtr<Block3D> blockBSW = this->getBlock(x1, x2, x3, l); + if (blockBSW) blockVector.push_back(blockBSW); + else if (l < levelDepth) this->getSubBlocksBottomSouthWest(x1, x2, x3, l, blockVector, levelDepth); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getBlocks(int level, std::vector<SPtr<Block3D>>& blockVector) +{ + for (Block3DMap::value_type b : levelSet[level]) + { + blockVector.push_back(b.second); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getBlocks(int level, int rank, std::vector<SPtr<Block3D>>& blockVector) +{ + for (Block3DMap::value_type b : levelSet[level]) + { + SPtr<Block3D> block = b.second; + int blockRank = block->getRank(); + if (blockRank == rank) + { + blockVector.push_back(b.second); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getBlocks(int level, int rank, bool active, std::vector<SPtr<Block3D>>& blockVector) +{ + for (Block3DMap::value_type b : levelSet[level]) + { + SPtr<Block3D> block = b.second; + int blockRank = block->getRank(); + + if (blockRank == rank && active ? block->isActive() : block->isNotActive()) + { + blockVector.push_back(b.second); + } + } +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getFinestInitializedLevel() +{ + for (int i=Grid3DSystem::MAXLEVEL; i>=0; i--) if (this->levelSet[i].size() > 0) return(i); + return(-1); +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getCoarsestInitializedLevel() +{ + for (int i=0; i<=Grid3DSystem::MAXLEVEL; i++) if (this->levelSet[i].size() > 0) return(i); + return(-1); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setNX1(int nx1) +{ + this->nx1 = nx1; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setNX2(int nx2) +{ + this->nx2 = nx2; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setNX3(int nx3) +{ + this->nx3 = nx3; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getNX1() const +{ + return this->nx1; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getNX2() const +{ + return this->nx2; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getNX3() const +{ + return this->nx3; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::deleteBlocks(const std::vector<int>& ids) +{ + for (int i : ids) + { + SPtr<Block3D> block = getBlock(i); + if (block) this->deleteBlock(block); + } +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getNumberOfBlocks() +{ + int c = 0; + for (Block3DMap l : levelSet) + { + c += (int)l.size(); + } + return c; +} +////////////////////////////////////////////////////////////////////////// +int Grid3D::getNumberOfBlocks(int level) +{ + return (int)levelSet[level].size(); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getBlocksByCuboid(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<SPtr<Block3D>>& blocks) +{ + int coarsestLevel = this->getCoarsestInitializedLevel(); + int finestLevel = this->getFinestInitializedLevel(); + + ////////////////////////////////////////////////////////////////////////// + //MINIMALE BLOCK-INDIZES BESTIMMEN + // + //min: + double dMinX1 = trafo->transformForwardToX1Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + double dMinX2 = trafo->transformForwardToX2Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + double dMinX3 = trafo->transformForwardToX3Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + + //Achtung, wenn minX1 genau auf grenze zwischen zwei bloecken -> der "kleinere" muss genommen werden, + //da beim Transformieren der "groessere" Index rauskommt + int iMinX1 = (int)dMinX1; if (UbMath::zero(dMinX1-iMinX1)) iMinX1-=1; + int iMinX2 = (int)dMinX2; if (UbMath::zero(dMinX2-iMinX2)) iMinX2-=1; + int iMinX3 = (int)dMinX3; if (UbMath::zero(dMinX3-iMinX3)) iMinX3-=1; + + //max (hier kann die Zusatzabfrage vernachlaessigt werden): + int iMaxX1 = (int)(trafo->transformForwardToX1Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + int iMaxX2 = (int)(trafo->transformForwardToX2Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + int iMaxX3 = (int)(trafo->transformForwardToX3Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + + SPtr<Block3D> block; + + //set, um doppelte bloecke zu vermeiden, die u.U. bei periodic auftreten koennen + std::set<SPtr<Block3D>> blockset; + for (int level=coarsestLevel; level<=finestLevel; level++) + { + //damit bei negativen werten auch der "kleinere" genommen wird -> floor! + int minx1 = (int)std::floor((double)iMinX1/(1<<(finestLevel-level))); + int minx2 = (int)std::floor((double)iMinX2/(1<<(finestLevel-level))); + int minx3 = (int)std::floor((double)iMinX3/(1<<(finestLevel-level))); + + int maxx1 = iMaxX1/(1<<(finestLevel-level)); + int maxx2 = iMaxX2/(1<<(finestLevel-level)); + int maxx3 = iMaxX3/(1<<(finestLevel-level)); + + for (int ix1=minx1; ix1<=maxx1; ix1++) + for (int ix2=minx2; ix2<=maxx2; ix2++) + for (int ix3=minx3; ix3<=maxx3; ix3++) + if ((block=this->getBlock(ix1, ix2, ix3, level))) + { + if (block->getRank() == rank) + { + blockset.insert(block); + } + } + } + + blocks.resize(blockset.size()); + std::copy(blockset.begin(), blockset.end(), blocks.begin()); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getBlocksByCuboid(int level, double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<SPtr<Block3D>>& blocks) +{ + ////////////////////////////////////////////////////////////////////////// + //MINIMALE BLOCK-INDIZES BESTIMMEN + // + //min: + double dMinX1 = trafo->transformForwardToX1Coordinate(minX1, minX2, minX3)*(1<<level); + double dMinX2 = trafo->transformForwardToX2Coordinate(minX1, minX2, minX3)*(1<<level); + double dMinX3 = trafo->transformForwardToX3Coordinate(minX1, minX2, minX3)*(1<<level); + + //Achtung, wenn minX1 genau auf grenze zwischen zwei bloecken -> der "kleinere" muss genommen werden: + int iMinX1 = (int)dMinX1; if (UbMath::zero(dMinX1-iMinX1)) iMinX1-=1; + int iMinX2 = (int)dMinX2; if (UbMath::zero(dMinX2-iMinX2)) iMinX2-=1; + int iMinX3 = (int)dMinX3; if (UbMath::zero(dMinX3-iMinX3)) iMinX3-=1; + + //max: + int iMaxX1 = (int)(trafo->transformForwardToX1Coordinate(maxX1, maxX2, maxX3)*(1<<level)); + int iMaxX2 = (int)(trafo->transformForwardToX2Coordinate(maxX1, maxX2, maxX3)*(1<<level)); + int iMaxX3 = (int)(trafo->transformForwardToX3Coordinate(maxX1, maxX2, maxX3)*(1<<level)); + + + //set, um doppelte bloecke zu vermeiden, die u.U. bei periodic auftreten koennen + std::set<SPtr<Block3D>> blockset; + SPtr<Block3D> block; + + for (int ix1=iMinX1; ix1<=iMaxX1; ix1++) + for (int ix2=iMinX2; ix2<=iMaxX2; ix2++) + for (int ix3=iMinX3; ix3<=iMaxX3; ix3++) + if ((block=this->getBlock(ix1, ix2, ix3, level))) + { + if (block->getRank() == rank) + { + blockset.insert(block); + } + } + + blocks.resize(blockset.size()); + std::copy(blockset.begin(), blockset.end(), blocks.begin()); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::getAllBlocksByCuboid(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<SPtr<Block3D>>& blocks) +{ + int coarsestLevel = this->getCoarsestInitializedLevel(); + int finestLevel = this->getFinestInitializedLevel(); + + ////////////////////////////////////////////////////////////////////////// + //MINIMALE BLOCK-INDIZES BESTIMMEN + // + //min: + double dMinX1 = trafo->transformForwardToX1Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + double dMinX2 = trafo->transformForwardToX2Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + double dMinX3 = trafo->transformForwardToX3Coordinate(minX1, minX2, minX3)*(1<<finestLevel); + + //Achtung, wenn minX1 genau auf grenze zwischen zwei bloecken -> der "kleinere" muss genommen werden, + //da beim Transformieren der "groessere" Index rauskommt + int iMinX1 = (int)dMinX1; if (UbMath::zero(dMinX1-iMinX1)) iMinX1-=1; + int iMinX2 = (int)dMinX2; if (UbMath::zero(dMinX2-iMinX2)) iMinX2-=1; + int iMinX3 = (int)dMinX3; if (UbMath::zero(dMinX3-iMinX3)) iMinX3-=1; + + //max (hier kann die Zusatzabfrage vernachlaessigt werden): + int iMaxX1 = (int)(trafo->transformForwardToX1Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + int iMaxX2 = (int)(trafo->transformForwardToX2Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + int iMaxX3 = (int)(trafo->transformForwardToX3Coordinate(maxX1, maxX2, maxX3)*(1<<finestLevel)); + + SPtr<Block3D> block; + + //set, um doppelte bloecke zu vermeiden, die u.U. bei periodic auftreten koennen + std::set<SPtr<Block3D>> blockset; + for (int level=coarsestLevel; level<=finestLevel; level++) + { + //damit bei negativen werten auch der "kleinere" genommen wird -> floor! + int minx1 = (int)std::floor((double)iMinX1/(1<<(finestLevel-level))); + int minx2 = (int)std::floor((double)iMinX2/(1<<(finestLevel-level))); + int minx3 = (int)std::floor((double)iMinX3/(1<<(finestLevel-level))); + + int maxx1 = iMaxX1/(1<<(finestLevel-level)); + int maxx2 = iMaxX2/(1<<(finestLevel-level)); + int maxx3 = iMaxX3/(1<<(finestLevel-level)); + + for (int ix1=minx1; ix1<=maxx1; ix1++) + for (int ix2=minx2; ix2<=maxx2; ix2++) + for (int ix3=minx3; ix3<=maxx3; ix3++) + if ((block=this->getBlock(ix1, ix2, ix3, level))) + { + if (block) + { + blockset.insert(block); + } + } + } + + blocks.resize(blockset.size()); + std::copy(blockset.begin(), blockset.end(), blocks.begin()); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::calcStartCoordinatesAndDelta(SPtr<Block3D> block, double& worldX1, double& worldX2, double& worldX3, double& deltaX) +{ + int blocklevel = block->getLevel(); + worldX1 = block->getX1()/(float)(1<<blocklevel); + worldX2 = block->getX2()/(float)(1<<blocklevel); + worldX3 = block->getX3()/(float)(1<<blocklevel); + deltaX = (double)1.0/(double)(this->blockNx1*(double)(1<<blocklevel)); + + if (this->trafo) + { + double x1tmp = worldX1, x2tmp = worldX2, x3tmp = worldX3; + worldX1 = this->trafo->transformBackwardToX1Coordinate(x1tmp, x2tmp, x3tmp); + worldX2 = this->trafo->transformBackwardToX2Coordinate(x1tmp, x2tmp, x3tmp); + worldX3 = this->trafo->transformBackwardToX3Coordinate(x1tmp, x2tmp, x3tmp); + deltaX = this->trafo->getX1CoordinateScaling()/(double)(this->blockNx1*(double)(1<<blocklevel)); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::calcStartCoordinatesWithOutOverlap(SPtr<Block3D> block, double& worldX1, double& worldX2, double& worldX3) +{ + int blocklevel = block->getLevel(); + worldX1 = block->getX1()/(float)(1<<blocklevel); + worldX2 = block->getX2()/(float)(1<<blocklevel); + worldX3 = block->getX3()/(float)(1<<blocklevel); + + if (this->trafo) + { + double x1tmp = worldX1, x2tmp = worldX2, x3tmp = worldX3; + worldX1 = this->trafo->transformBackwardToX1Coordinate(x1tmp, x2tmp, x3tmp); + worldX2 = this->trafo->transformBackwardToX2Coordinate(x1tmp, x2tmp, x3tmp); + worldX3 = this->trafo->transformBackwardToX3Coordinate(x1tmp, x2tmp, x3tmp); + } +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::setTimeStep(double step) +{ + timeStep = step; +} +////////////////////////////////////////////////////////////////////////// +double Grid3D::getTimeStep() const +{ + return timeStep; +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::fillExtentWithBlocks(UbTupleInt3 minInd, UbTupleInt3 maxInd) +{ + for (int x3 = val<3>(minInd); x3 < val<3>(maxInd); x3++) + { + for (int x2 = val<2>(minInd); x2 < val<2>(maxInd); x2++) + { + for (int x1 = val<1>(minInd); x1 < val<1>(maxInd); x1++) + { + SPtr<Block3D> block(new Block3D(x1, x2, x3, 0)); + this->addBlock(block); + } + } + } +} +////////////////////////////////////////////////////////////////////////// +//void Grid3D::notifyObservers( double step ) +//{ +// for(ObserverPtr o, observers) +// { +// o->update(step); +// } +// +// //std::list<ObserverWeakPtr>::iterator iter = observers.begin(); +// +// //GridObserversSet::iterator iter = observers.begin(); +// //while(iter != observers.end()) +// //{ +// // if ((*iter).expired()) +// // { +// // iter = observers.erase(iter); +// // } +// // else +// // { +// // ObserverPtr observer = (*iter).lock(); // create a shared_ptr from the weak_ptr +// // observer->update(step); +// // ++iter; +// // } +// //} +// +//} +////////////////////////////////////////////////////////////////////////// +//void Grid3D::addObserver( ObserverPtr observer ) +//{ +// observers.insert(observer); +// //observers.push_back(observer); +//} +//////////////////////////////////////////////////////////////////////////// +//void Grid3D::removeObserver( ObserverPtr observer ) +//{ +// observers.erase(observer); +// //observers.remove(observer); +//} +////////////////////////////////////////////////////////////////////////// +void Grid3D::deleteBlockIDs() +{ + this->blockIdMap.clear(); +} +////////////////////////////////////////////////////////////////////////// +void Grid3D::renumberBlockIDs() +{ + deleteBlockIDs(); + + int startLevel = getCoarsestInitializedLevel(); + int stopLevel = getFinestInitializedLevel(); + int counter = 0; + + for (int l = startLevel; l <= stopLevel; l++) + { + std::vector<SPtr<Block3D>> blockVector; + getBlocks(l, blockVector); + for (SPtr<Block3D> block : blockVector) + { + block->setGlobalID(counter); + blockIdMap.insert(std::make_pair(counter, block)); + //Block3D::setMaxGlobalID(counter); + counter++; + } + } +} + + +////////////////////////////////////////////////////////////////////////// + diff --git a/VirtualFluidsCore/Grid/Grid3D.h b/VirtualFluidsCore/Grid/Grid3D.h new file mode 100644 index 0000000000000000000000000000000000000000..e392b90a077c6168914befbf52327698811c9a75 --- /dev/null +++ b/VirtualFluidsCore/Grid/Grid3D.h @@ -0,0 +1,274 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Grid.h +//! \ingroup Grid +//! \author Konstantin Kutscher, Soeren Freudiger, Sebastian Geller +//======================================================================================= + +#ifndef GRID3D_H +#define GRID3D_H + + +#include <vector> +#include <map> +#include <PointerDefinitions.h> + +#include <basics/utilities/Vector3D.h> +#include <basics/utilities/UbTuple.h> +#include <basics/utilities/UbKeys.h> + +class CoordinateTransformation3D; + +#include <Block3DVisitor.h> +#include <Grid3DVisitor.h> + +class Communicator; +class Block3D; +class Interactor3D; + +#define OFFSET 0.5 + +//! A class implements block grid +////////////////////////////////////////////////////////////////////////// +class Grid3D : public enableSharedFromThis<Grid3D> +{ +public: + typedef UbKeys::Key3<int> Block3DKey; + typedef std::map< Block3DKey, SPtr<Block3D> > Block3DMap; + typedef std::map< int, SPtr<Block3D> > BlockIDMap; + typedef std::vector<Block3DMap> LevelSet; + typedef std::vector<SPtr<Interactor3D> > Interactor3DSet; + +public: + Grid3D(); + Grid3D(SPtr<Communicator> comm); + Grid3D(SPtr<Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3); + virtual ~Grid3D(){} + ////////////////////////////////////////////////////////////////////////// + //blocks control + void addBlock(SPtr<Block3D> block); + bool deleteBlock(SPtr<Block3D> block); + bool deleteBlock(int ix1, int ix2, int ix3, int level); + void deleteBlocks(const std::vector<int>& ids); + void replaceBlock(SPtr<Block3D> block); + SPtr<Block3D> getBlock(int ix1, int ix2, int ix3, int level) const; + SPtr<Block3D> getBlock(int id) const; + void getBlocksByCuboid(double minX1, double minX2, double minX3, + double maxX1, double maxX2, double maxX3, + std::vector<SPtr<Block3D>>& blocks); + void getBlocksByCuboid(int level, double minX1, double minX2, double minX3, + double maxX1, double maxX2, double maxX3, + std::vector<SPtr<Block3D>>& blocks); + void getAllBlocksByCuboid(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<SPtr<Block3D>>& blocks); + //!get blocks for level + void getBlocks(int level, std::vector<SPtr<Block3D>>& blockVector); + //!get blocks for level with current rank + void getBlocks(int level, int rank, std::vector<SPtr<Block3D>>& blockVector); + //!get only active or not active blocks + void getBlocks(int level, int rank, bool active, std::vector<SPtr<Block3D>>& blockVector); + int getNumberOfBlocks(); + int getNumberOfBlocks(int level); + BlockIDMap& getBlockIDs(); + void deleteBlockIDs(); + void renumberBlockIDs(); + SPtr<Block3D> getSuperBlock(SPtr<Block3D> block); + SPtr<Block3D> getSuperBlock(int ix1, int ix2, int ix3, int level); + void getSubBlocks(SPtr<Block3D> block, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getSubBlocks(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blockVector); + SPtr<Block3D> getNeighborBlock(int dir, int ix1, int ix2, int ix3, int level) const; + SPtr<Block3D> getNeighborBlock(int dir, SPtr<Block3D> block) const; + bool expandBlock(int ix1, int ix2, int ix3, int level); + SPtr<Block3D> collapseBlock(int fix1, int fix2, int fix3, int flevel, int levelDepth); + void getAllNeighbors(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getAllNeighbors(SPtr<Block3D> block, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborBlocksForDirection(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborBlocksForDirectionWithDirZero(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + + void getNeighborsZero(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTop(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottom(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + + void getNeighborsNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + + void getNeighborsTopNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + + void getNeighborsBottomNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + + void getNeighborsTopNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsTopSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + void getNeighborsBottomSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<SPtr<Block3D>>& blocks); + ////////////////////////////////////////////////////////////////////////// + //level control + int getFinestInitializedLevel(); + int getCoarsestInitializedLevel(); + ////////////////////////////////////////////////////////////////////////// + void deleteConnectors(); + ////////////////////////////////////////////////////////////////////////// + //interactors control + void addInteractor(SPtr<Interactor3D> interactor); + void addAndInitInteractor(SPtr<Interactor3D> interactor, double timestep=0); + Interactor3DSet getInteractors(); + ////////////////////////////////////////////////////////////////////////// + //visitors + void accept(Block3DVisitor& blockVisitor); + void accept(Grid3DVisitor& gridVisitor); + void accept(SPtr<Grid3DVisitor> gridVisitor); + ////////////////////////////////////////////////////////////////////////// + //bundle and rank for distributed memory + void setBundle(int bundle); + int getBundle() const; + int getRank() const; + void setRank(int rank); + ////////////////////////////////////////////////////////////////////////// + //periodic boundary + bool isPeriodicX1() const; + bool isPeriodicX2() const; + bool isPeriodicX3() const; + void setPeriodicX1(bool value); + void setPeriodicX2(bool value); + void setPeriodicX3(bool value); + ////////////////////////////////////////////////////////////////////////// + //Topology + UbTupleInt3 getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord) const; + UbTupleInt3 getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord, int level) const; + UbTupleDouble3 getBlockLengths(SPtr<Block3D> block) const; + UbTupleDouble6 getBlockOversize() const ; + void setCoordinateTransformator(SPtr<CoordinateTransformation3D> trafo); + const SPtr<CoordinateTransformation3D> getCoordinateTransformator() const ; + void setDeltaX(double dx); + void setDeltaX(double worldUnit, double gridUnit); + double getDeltaX(int level) const; + double getDeltaX(SPtr<Block3D> block) const; + UbTupleDouble3 getNodeOffset(SPtr<Block3D> block) const ; + Vector3D getNodeCoordinates(SPtr<Block3D> block, int ix1, int ix2, int ix3) const; + UbTupleInt3 getNodeIndexes(SPtr<Block3D> block, double nodeX1Coord, double nodeX2Coord, double nodeX3Coord) const; + void setBlockNX(int nx1, int nx2, int nx3); + UbTupleInt3 getBlockNX() const; + UbTupleDouble3 getBlockWorldCoordinates(SPtr<Block3D> block) const; + UbTupleDouble3 getBlockWorldCoordinates(int blockX1Index, int blockX2Index, int blockX3Index, int level) const; + void setNX1(int nx1); + void setNX2(int nx2); + void setNX3(int nx3); + int getNX1() const; + int getNX2() const; + int getNX3() const; + void calcStartCoordinatesAndDelta(SPtr<Block3D> block, double& worldX1, double& worldX2, double& worldX3, double& deltaX); + void calcStartCoordinatesWithOutOverlap(SPtr<Block3D> block, double& worldX1, double& worldX2, double& worldX3); + ////////////////////////////////////////////////////////////////////////// + //LBM + //double getDeltaT(SPtr<Block3D>) const; + ////////////////////////////////////////////////////////////////////////// + void setTimeStep(double step); + double getTimeStep() const; + +protected: + void checkLevel(int level); + bool hasLevel(int level) const; + + void fillExtentWithBlocks( UbTupleInt3 minInd, UbTupleInt3 maxInd ); + + void getSubBlocksZero(int ix1, int ix2, int ix3, int level,std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + + void getSubBlocksEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksNorth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksSouth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTop(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottom(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + + void getSubBlocksSouthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksSouthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksNorthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksNorthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + + void getSubBlocksTopEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopNorth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopSouth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + + void getSubBlocksBottomEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomNorth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomSouth(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + + void getSubBlocksTopNorthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopNorthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopSouthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksTopSouthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomNorthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomNorthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomSouthEast(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + void getSubBlocksBottomSouthWest(int ix1, int ix2, int ix3, int level, std::vector<SPtr<Block3D>>& blockVector, int levelDepth); + +private: + LevelSet levelSet; + BlockIDMap blockIdMap; + Interactor3DSet interactors; + + int rank; + int bundle; + + bool periodicX1; + bool periodicX2; + bool periodicX3; + + int blockNx1; + int blockNx2; + int blockNx3; + + int nx1; + int nx2; + int nx3; + + SPtr<CoordinateTransformation3D> trafo; + double orgDeltaX; + + double timeStep; + +}; + +#endif diff --git a/VirtualFluidsCore/Grid/Grid3DSystem.cpp b/VirtualFluidsCore/Grid/Grid3DSystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7363f263a9ddbb21968d86960df856e9cb0f6e1f --- /dev/null +++ b/VirtualFluidsCore/Grid/Grid3DSystem.cpp @@ -0,0 +1,81 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Grid3DSystem.cpp +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#include <Grid3DSystem.h> + +namespace Grid3DSystem +{ + const int INVDIR[] = { INV_E , + INV_W , + INV_N , + INV_S , + INV_T , + INV_B , + INV_NE , + INV_NW , + INV_SE , + INV_SW , + INV_TE , + INV_TW , + INV_BE , + INV_BW , + INV_TN , + INV_TS , + INV_BN , + INV_BS , + INV_TNE, + INV_TNW, + INV_TSE, + INV_TSW, + INV_BNE, + INV_BNW, + INV_BSE, + INV_BSW }; + + //index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + //direction: E, W, N, S, T, B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW + const int EX1[] = { 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1 }; + const int EX2[] = { 0, 0, 1, -1, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1 }; + const int EX3[] = { 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1 }; +} + +////////////////////////////////////////////////////////////////////////// +const int& Grid3DSystem::getInvertDirection(const int& direction) +{ +#ifdef _DEBUG + if(direction<STARTDIR || direction>ENDDIR) + throw UbException(UB_EXARGS,"unknown direction"); +#endif + return INVDIR[direction]; +} + diff --git a/VirtualFluidsCore/Grid/Grid3DSystem.h b/VirtualFluidsCore/Grid/Grid3DSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..bbcb213162e0a16fa514ea41d7cb055ddd27dd4d --- /dev/null +++ b/VirtualFluidsCore/Grid/Grid3DSystem.h @@ -0,0 +1,185 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Grid3DSystem.h +//! \ingroup Grid +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef Grid3DSystem_H +#define Grid3DSystem_H + +#include <cmath> +#include <iostream> +#include <string> + +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbException.h> + + +namespace Grid3DSystem +{ + static const int STARTDIR = 0; + + static const int E /*f1 */ = 0; + static const int W /*f2 */ = 1; + static const int N /*f3 */ = 2; + static const int S /*f4 */ = 3; + static const int T /*f5 */ = 4; + static const int B /*f6 */ = 5; + static const int NE /*f7 */ = 6; + static const int SW /*f8 */ = 7; + static const int SE /*f9 */ = 8; + static const int NW /*f10*/ = 9; + static const int TE /*f11*/ = 10; + static const int BW /*f12*/ = 11; + static const int BE /*f13*/ = 12; + static const int TW /*f14*/ = 13; + static const int TN /*f15*/ = 14; + static const int BS /*f16*/ = 15; + static const int BN /*f17*/ = 16; + static const int TS /*f18*/ = 17; + static const int TNE = 18; + static const int TNW = 19; + static const int TSE = 20; + static const int TSW = 21; + static const int BNE = 22; + static const int BNW = 23; + static const int BSE = 24; + static const int BSW = 25; + static const int REST /*f0 */ = 26; + + static const int ENDDIR = 25; + + static const int INV_E = W; + static const int INV_W = E; + static const int INV_N = S; + static const int INV_S = N; + static const int INV_T = B; + static const int INV_B = T; + static const int INV_NE = SW; + static const int INV_NW = SE; + static const int INV_SE = NW; + static const int INV_SW = NE; + static const int INV_TE = BW; + static const int INV_TW = BE; + static const int INV_BE = TW; + static const int INV_BW = TE; + static const int INV_TN = BS; + static const int INV_TS = BN; + static const int INV_BN = TS; + static const int INV_BS = TN; + static const int INV_TNE = BSW; + static const int INV_TNW = BSE; + static const int INV_TSE = BNW; + static const int INV_TSW = BNE; + static const int INV_BNE = TSW; + static const int INV_BNW = TSE; + static const int INV_BSE = TNW; + static const int INV_BSW = TNE; + + extern const int INVDIR[ENDDIR+1]; + + static const int MAXLEVEL = 25; + + extern const int EX1[ENDDIR+1]; + extern const int EX2[ENDDIR+1]; + extern const int EX3[ENDDIR+1]; + + inline std::string getDirectionString(int direction) + { + switch(direction) + { + case E : return "E"; + case W : return "W"; + case N : return "N"; + case S : return "S"; + case T : return "T"; + case B : return "B"; + case NE : return "NE"; + case NW : return "NW"; + case SE : return "SE"; + case SW : return "SW"; + case TE : return "TE"; + case TW : return "TW"; + case BE : return "BE"; + case BW : return "BW"; + case TN : return "TN"; + case TS : return "TS"; + case BN : return "BN"; + case BS : return "BS"; + case TNE : return "TNE"; + case TNW : return "TNW"; + case TSE : return "TSE"; + case TSW : return "TSW"; + case BNE : return "BNE"; + case BNW : return "BNW"; + case BSE : return "BSE"; + case BSW : return "BSW"; + default : return "Cell3DSystem::getDrectionString(...) - unknown dir"; + } + } + static const int& getInvertDirection(const int& direction); + +////////////////////////////////////////////////////////////////////////// + static inline void setNeighborCoordinatesForDirection(int &x1, int &x2,int &x3, const int& direction) + { + switch(direction) + { + case Grid3DSystem::E : x1++; break; + case Grid3DSystem::N : x2++; break; + case Grid3DSystem::T : x3++; break; + case Grid3DSystem::W : x1--; break; + case Grid3DSystem::S : x2--; break; + case Grid3DSystem::B : x3--; break; + case Grid3DSystem::NE : x1++; x2++; break; + case Grid3DSystem::NW : x1--; x2++; break; + case Grid3DSystem::SW : x1--; x2--; break; + case Grid3DSystem::SE : x1++; x2--; break; + case Grid3DSystem::TE : x1++; x3++; break; + case Grid3DSystem::BW : x1--; x3--; break; + case Grid3DSystem::BE : x1++; x3--; break; + case Grid3DSystem::TW : x1--; x3++; break; + case Grid3DSystem::TN : x2++; x3++; break; + case Grid3DSystem::BS : x2--; x3--; break; + case Grid3DSystem::BN : x2++; x3--; break; + case Grid3DSystem::TS : x2--; x3++; break; + case Grid3DSystem::TNE: x1++; x2++; x3++; break; + case Grid3DSystem::TNW: x1--; x2++; x3++; break; + case Grid3DSystem::TSE: x1++; x2--; x3++; break; + case Grid3DSystem::TSW: x1--; x2--; x3++; break; + case Grid3DSystem::BNE: x1++; x2++; x3--; break; + case Grid3DSystem::BNW: x1--; x2++; x3--; break; + case Grid3DSystem::BSE: x1++; x2--; x3--; break; + case Grid3DSystem::BSW: x1--; x2--; x3--; break; + default: throw UbException(UB_EXARGS,"no direction ..."); + } + } +} + +#endif diff --git a/VirtualFluidsCore/IncludsList.cmake b/VirtualFluidsCore/IncludsList.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5fed1de0af06af1a5942bac957f0b8909e0a7d76 --- /dev/null +++ b/VirtualFluidsCore/IncludsList.cmake @@ -0,0 +1,17 @@ +#directory pathes for header files + +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/BoundaryConditions) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Connectors) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Data) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Interactors) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/LBM) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Parallel) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Grid) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Visitors) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/CoProcessors) +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Utilities) + +INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty) + + diff --git a/VirtualFluidsCore/Interactors/CMakePackage.txt b/VirtualFluidsCore/Interactors/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Interactors/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp b/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..811a04691528b5820835a2aa1622ebad0782ddd8 --- /dev/null +++ b/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp @@ -0,0 +1,744 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27Interactor.cpp +//! \ingroup Interactor +//! \author Sören Freudiger +//! \author Sebastian Geller +//! \author Konstantin Kutscher +//======================================================================================= + +#include "D3Q27Interactor.h" +#include <basics/utilities/UbMath.h> +#include <basics/utilities/UbLogger.h> + +#include <basics/writer/WbWriterVtkXmlBinary.h> + +#include <GbCuboid3D.h> +#include <GbLine3D.h> +#include "Block3D.h" +#include "Grid3D.h" +#include "BCArray3D.h" +#include "BoundaryConditions.h" +#include "LBMKernel.h" +#include "BCProcessor.h" +#include "BCAdapter.h" + + +using namespace std; + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +D3Q27Interactor::D3Q27Interactor() : Interactor3D() +{ + this->reinitWithStoredQsFlag = false; + this->initRayVectors(); +} +////////////////////////////////////////////////////////////////////////// +D3Q27Interactor::D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type) +: Interactor3D(geoObject3D, grid, type), relevantForForces(false) +{ + this->reinitWithStoredQsFlag = false; + this->initRayVectors(); +} +////////////////////////////////////////////////////////////////////////// +D3Q27Interactor::D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, SPtr<BCAdapter> bcAdapter, int type) + : Interactor3D(geoObject3D, grid, type), relevantForForces(false) +{ + this->reinitWithStoredQsFlag = false; + this->addBCAdapter(bcAdapter); + this->initRayVectors(); +} +////////////////////////////////////////////////////////////////////////// +D3Q27Interactor::D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, SPtr<BCAdapter> bcAdapter, int type, Interactor3D::Accuracy a) + : Interactor3D(geoObject3D, grid, type, a), relevantForForces(false) +{ + this->reinitWithStoredQsFlag = false; + this->addBCAdapter(bcAdapter); + this->initRayVectors(); +} +////////////////////////////////////////////////////////////////////////// +D3Q27Interactor::~D3Q27Interactor() +{ + +} +////////////////////////////////////////////////////////////////////////// +void D3Q27Interactor::initRayVectors() +{ + int fdir; + double c1oS2 = UbMath::one_over_sqrt2; + double c1oS3 = UbMath::one_over_sqrt3; + fdir = D3Q27System::E; rayX1[fdir] = 1.0; rayX2[fdir] = 0.0; rayX3[fdir] = 0.0; + fdir = D3Q27System::W; rayX1[fdir] = -1.0; rayX2[fdir] = 0.0; rayX3[fdir] = 0.0; + fdir = D3Q27System::N; rayX1[fdir] = 0.0; rayX2[fdir] = 1.0; rayX3[fdir] = 0.0; + fdir = D3Q27System::S; rayX1[fdir] = 0.0; rayX2[fdir] = -1.0; rayX3[fdir] = 0.0; + fdir = D3Q27System::T; rayX1[fdir] = 0.0; rayX2[fdir] = 0.0; rayX3[fdir] = 1.0; + fdir = D3Q27System::B; rayX1[fdir] = 0.0; rayX2[fdir] = 0.0; rayX3[fdir] = -1.0; + fdir = D3Q27System::NE; rayX1[fdir] = c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] = 0.0; + fdir = D3Q27System::SW; rayX1[fdir] = -c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] = 0.0; + fdir = D3Q27System::SE; rayX1[fdir] = c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] = 0.0; + fdir = D3Q27System::NW; rayX1[fdir] = -c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] = 0.0; + fdir = D3Q27System::TE; rayX1[fdir] = c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = c1oS2; + fdir = D3Q27System::BW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = -c1oS2; + fdir = D3Q27System::BE; rayX1[fdir] = c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = -c1oS2; + fdir = D3Q27System::TW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = c1oS2; + fdir = D3Q27System::TN; rayX1[fdir] = 0.0; rayX2[fdir] = c1oS2; rayX3[fdir] = c1oS2; + fdir = D3Q27System::BS; rayX1[fdir] = 0.0; rayX2[fdir] =-c1oS2; rayX3[fdir] = -c1oS2; + fdir = D3Q27System::BN; rayX1[fdir] = 0.0; rayX2[fdir] = c1oS2; rayX3[fdir] = -c1oS2; + fdir = D3Q27System::TS; rayX1[fdir] = 0.0; rayX2[fdir] =-c1oS2; rayX3[fdir] = c1oS2; + + fdir = D3Q27System::TNW; rayX1[fdir] = -c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = c1oS3; + fdir = D3Q27System::TNE; rayX1[fdir] = c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = c1oS3; + fdir = D3Q27System::TSW; rayX1[fdir] = -c1oS3; rayX2[fdir] =-c1oS3; rayX3[fdir] = c1oS3; + fdir = D3Q27System::TSE; rayX1[fdir] = c1oS3; rayX2[fdir] =-c1oS3; rayX3[fdir] = c1oS3; + fdir = D3Q27System::BNW; rayX1[fdir] = -c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = -c1oS3; + fdir = D3Q27System::BNE; rayX1[fdir] = c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = -c1oS3; + fdir = D3Q27System::BSW; rayX1[fdir] = -c1oS3; rayX2[fdir] =-c1oS3; rayX3[fdir] = -c1oS3; + fdir = D3Q27System::BSE; rayX1[fdir] = c1oS3; rayX2[fdir] =-c1oS3; rayX3[fdir] = -c1oS3; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27Interactor::initInteractor(const double& timeStep) +{ + UBLOG(logDEBUG5,"D3Q27Interactor::initInteractor - "<<" for timestep = "<<timeStep); + + ////////////////////////////////////////////////////////////////////////// + //init bcs + int nofAdapter = (int)bcAdapters.size(); + if(nofAdapter==0) UBLOG(logWARNING,"WARNING - D3Q27Interactor::initInteractor Warning - no nodeAdapter available"); + bool needTimeDependence = false; + for(int pos=0; pos<nofAdapter; ++pos) + { + bcAdapters[pos]->init(this,timeStep); + if(bcAdapters[pos]->isTimeDependent()) needTimeDependence = true; + } + if(needTimeDependence) this->setTimeDependent(); + else this->unsetTimeDependent(); + + Interactor3D::initInteractor(timeStep); +} +////////////////////////////////////////////////////////////////////////// +void D3Q27Interactor::updateInteractor(const double& timestep) +{ + UBLOG(logDEBUG5,"D3Q27Interactor::updateInteractor - for timestep = "<<timestep); + + ////////////////////////////////////////////////////////////////////////// + //update bcs + int nofAdapter = (int)bcAdapters.size(); + if(nofAdapter==0) UBLOG(logERROR,"WARNING - D3Q27Interactor::updateInteractor Warning - no nodeAdapter available for "); + + bool needTimeDependence = false; + + for(int pos=0; pos<nofAdapter; ++pos) + { + bcAdapters[pos]->update(this,timestep); + if(bcAdapters[pos]->isTimeDependent()) needTimeDependence = true; + } + if(needTimeDependence) this->setTimeDependent(); + else this->unsetTimeDependent(); + + for(BcNodeIndicesMap::value_type t : bcNodeIndicesMap) + { + SPtr<Block3D> block = t.first; + std::set< std::vector<int> >& transNodeIndicesSet = t.second; + + if(block->isNotActive() || !block) continue; + + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + + set< std::vector<int> >::iterator setPos; + + for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end(); ++setPos) + { + int x1 = (*setPos)[0]; + int x2 = (*setPos)[1]; + int x3 = (*setPos)[2]; + Vector3D coords = grid.lock()->getNodeCoordinates(block, x1, x2, x3); + double worldX1 = coords[0]; + double worldX2 = coords[1]; + double worldX3 = coords[2]; + + SPtr<BoundaryConditions> bc = bcArray->getBC(x1,x2,x3); + if(bc) //may be that the BC has been deleted by the solid setting of another interactor + { + for(size_t i=0; i<bcAdapters.size(); i++) + bcAdapters[i]->adaptBC(*this,bc,worldX1,worldX2,worldX3,timestep); + } + } + } +} +////////////////////////////////////////////////////////////////////////// +// calculation takes place in the real coordinate system !!! +// not normalized! +// x1, x2, x3 are the coordinates at the bottom left of the "system" +// extendedBoundingGeoOfGeoObject MUST already have been magnified by delta_x_level in each direction for SOLID +bool D3Q27Interactor::setDifferencesToGbObject3D(const SPtr<Block3D> block) +{ + if(!block) return false; + + if(block->isNotActive()) return false;//continue; + + bcNodeIndicesMap[block] = set< std::vector<int> >(); + set< std::vector<int> >& transNodeIndices = bcNodeIndicesMap[block]; + solidNodeIndicesMap[block] = set< UbTupleInt3 >(); + set< UbTupleInt3 >& solidNodeIndices = solidNodeIndicesMap[block]; + + + double timestep = 0; + bool oneEntryGotBC = false; + bool gotQs = false; + SPtr<BoundaryConditions> bc; + + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + + double internX1,internX2,internX3; + + + //width of ghost layer + int gl = kernel->getGhostLayerWidth(); + + int startIX1 = 0; + int startIX2 = 0; + int startIX3 = 0; + int stopIX1 = (int)bcArray->getNX1(); + int stopIX2 = (int)bcArray->getNX2(); + int stopIX3 = (int)bcArray->getNX3(); + + double dx = grid.lock()->getDeltaX(block); + UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block); + + //other boundingRect than in init, because here the boundrect has to be increased by one dx + GbCuboid3D extendedBoundingGeoOfGeoObject( geoObject3D->getX1Minimum()-1.02*dx + , geoObject3D->getX2Minimum()-1.02*dx + , geoObject3D->getX3Minimum()-1.02*dx + , geoObject3D->getX1Maximum()+1.02*dx + , geoObject3D->getX2Maximum()+1.02*dx + , geoObject3D->getX3Maximum()+1.02*dx ); + + double deltaX1=dx, deltaX2 =dx, deltaX3=dx; + + if( geoObject3D->hasRaytracing() + || (this->isInverseSolid() && geoObject3D->raytracingSupportsPointsInside() ) ) + { + //if deltaX1==deltaX2==deltaX3 (must for LB!!) + if(!UbMath::zero( deltaX1-deltaX2 + deltaX1-deltaX3 + deltaX2-deltaX3 ) ) + throw UbException(UB_EXARGS,"fuer den bei LB nicht vorkommenden Fall deltaX1!=deltaX2!=deltaX3 nicht implementiert "); + + vector<double> distNeigh(D3Q27System::FENDDIR+1, UbMath::sqrt2*deltaX1); + distNeigh[D3Q27System::E] = distNeigh[D3Q27System::W] = distNeigh[D3Q27System::N] = deltaX1; + distNeigh[D3Q27System::S] = distNeigh[D3Q27System::T] = distNeigh[D3Q27System::B] = deltaX1; + distNeigh[D3Q27System::NE] = distNeigh[D3Q27System::NW] = distNeigh[D3Q27System::SW] = distNeigh[D3Q27System::SE] = UbMath::sqrt2*deltaX1; + distNeigh[D3Q27System::TE] = distNeigh[D3Q27System::TN] = distNeigh[D3Q27System::TW] = distNeigh[D3Q27System::TS] = UbMath::sqrt2*deltaX1; + distNeigh[D3Q27System::BE] = distNeigh[D3Q27System::BN] = distNeigh[D3Q27System::BW] = distNeigh[D3Q27System::BS] = UbMath::sqrt2*deltaX1; + distNeigh[D3Q27System::TNE] = distNeigh[D3Q27System::TNW] = distNeigh[D3Q27System::TSE] = distNeigh[D3Q27System::TSW] = UbMath::sqrt3*deltaX1; + distNeigh[D3Q27System::BNE] = distNeigh[D3Q27System::BNW] = distNeigh[D3Q27System::BSE] = distNeigh[D3Q27System::BSW] = UbMath::sqrt3*deltaX1; + double q; + bool pointOnBoundary = false; + +//#ifdef _OPENMP +// #pragma omp parallel for private(internX1,internX2,internX3,gotQs,bc,q ) +//#endif + for(int ix3=startIX3; ix3<stopIX3; ix3++) + { + for(int ix2=startIX2; ix2<stopIX2; ix2++) + { + for(int ix1=startIX1; ix1<stopIX1; ix1++) + { + //TODO: further, investigate if this is not a mistake + if(bcArray->isUndefined(ix1, ix2, ix3)) continue; + + Vector3D coords = grid.lock()->getNodeCoordinates(block, ix1, ix2, ix3); + internX1 = coords[0]; + internX2 = coords[1]; + internX3 = coords[2]; + + // Point in the object test is superfluous, since the start and stop indices already exist + // are determined -> only point-in-cube indexes are considered + if(extendedBoundingGeoOfGeoObject.isPointInGbObject3D(internX1,internX2,internX3)) + { + if(this->isSolid() ) + { + if(this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3)) + { + { + solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3)); + bcArray->setSolid(ix1,ix2,ix3); + } + continue; + } + } + else if( this->isInverseSolid() ) + { + //in inverse solid all nodes are OUTSIDE and on the boundary SOLID + if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) + || pointOnBoundary == true ) + { + + { + solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3)); + bcArray->setSolid(ix1,ix2,ix3); + } + continue; + } + } + + if(bcArray->isSolid(ix1,ix2,ix3)) + continue; + + gotQs = false; + + for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) + { + q = geoObject3D->getIntersectionRaytraceFactor(internX1,internX2,internX3,rayX1[fdir],rayX2[fdir],rayX3[fdir]); + q /= distNeigh[fdir]; + + //assert(UbMath::lessEqual(q, 1.0)); + + if( UbMath::inClosedInterval(q, 1.0, 1.0) ) q = 1.0; + if( UbMath::greater(q, 0.0) && UbMath::lessEqual(q, 1.0) ) + { + //#pragma omp critical (BC_CHANGE) + { + bc = bcArray->getBC(ix1,ix2,ix3); + if(!bc) + { + bc = SPtr<BoundaryConditions>(new BoundaryConditions); + bcArray->setBC(ix1,ix2,ix3,bc); + } + + if(bc->hasNoSlipBoundary()) + { + bc->setBoundaryVelocityX1(0.0); + bc->setBoundaryVelocityX2(0.0); + bc->setBoundaryVelocityX3(0.0); + } + + for(int index=(int)bcAdapters.size()-1; index>=0; --index) + bcAdapters[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir, timestep); + } + + gotQs=true; + } + } + + if(gotQs) + { + { + oneEntryGotBC = true; + + std::vector<int> p(3); + p[0]=ix1; p[1]=ix2; p[2]=ix3; + transNodeIndices.insert(p); + + for(int index=(int)bcAdapters.size()-1; index>=0; --index) + bcAdapters[index]->adaptBC(*this,bc,internX1,internX2,internX3, timestep); + } + } + } + else if( this->isInverseSolid() ) + { + //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID + if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) + || pointOnBoundary == true ) + { + { + solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3)); + bcArray->setSolid(ix1,ix2,ix3); + } + continue; + } + } + } + } + } + } + else //clipping -> slower (currently also used for all inverse Solid objects whose raytracing does not work for nodes INSIDE the geo) + { + bool pointOnBoundary = false; + for(int ix1=startIX1; ix1<stopIX1; ix1++) + { + for(int ix2=startIX2; ix2<stopIX2; ix2++) + { + for(int ix3=startIX3; ix3<stopIX3; ix3++) + { + if(bcArray->isSolid(ix1,ix2,ix3) || bcArray->isUndefined(ix1, ix2, ix3)) continue; + + Vector3D coords = grid.lock()->getNodeCoordinates(block, ix1, ix2, ix3); + internX1 = coords[0]; + internX2 = coords[1]; + internX3 = coords[2]; + + if(extendedBoundingGeoOfGeoObject.isPointInGbObject3D(internX1,internX2,internX3)) + { + if( this->isSolid() && this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3) ) + { + { + solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3)); + bcArray->setSolid(ix1,ix2,ix3); + } + continue; + } + else if( this->isInverseSolid() ) + { + //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID + if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) + || pointOnBoundary == true ) + { + { + solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3)); + bcArray->setSolid(ix1,ix2,ix3); + } + continue; + } + } + + gotQs = false; + + GbPoint3D pointA(internX1,internX2,internX3); + for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) + { + double x1B = internX1+D3Q27System::DX1[fdir]*deltaX1; + double x2B = internX2+D3Q27System::DX2[fdir]*deltaX2; + double x3B = internX3+D3Q27System::DX3[fdir]*deltaX3; + + GbPoint3D pointB(x1B,x2B,x3B); + GbLine3D* clippedLine = this->geoObject3D->createClippedLine3D(pointA, pointB); + + if(clippedLine) + { + double q=0.0; + if( !this->isInverseSolid() ) //A is outside + { + double distanceAB = pointA.getDistance(&pointB); //pointA to B + double distanceAP = UbMath::min(pointA.getDistance(clippedLine->getPoint1()), + pointA.getDistance(clippedLine->getPoint2()) ); + q = distanceAP/distanceAB; + } + else + { + bool pointIsOnBoundary = false; + if( !clippedLine->getPoint1()->equals(&pointB) + && !clippedLine->getPoint2()->equals(&pointB) ) + { + //A is inside, a clipped line must not contain B + double distanceAB = pointA.getDistance(&pointB); //pointA to B + double distanceAP = clippedLine->getLength(); + q = distanceAP/distanceAB; + } + else if( this->geoObject3D->isPointInGbObject3D( pointB.getX1Coordinate() + ,pointB.getX2Coordinate() + ,pointB.getX3Coordinate() + ,pointIsOnBoundary ) + && pointIsOnBoundary ) + { + //A is definitely inside, B is exactly on ObjectBoundary => q = 1.0 + q=1.0; + } + else + { + q = 0.0; + } + } + + if(UbMath::inClosedInterval(q, 1.0, 1.0)) q = 1.0; + if(UbMath::lessEqual(q, 1.0) && UbMath::greater(q, 0.0)) + { + { + bc = bcArray->getBC(ix1,ix2,ix3); + if(!bc) + { + bc = SPtr<BoundaryConditions>(new BoundaryConditions); + bcArray->setBC(ix1,ix2,ix3,bc); + } + for(int index=(int)bcAdapters.size()-1; index>=0; --index) + bcAdapters[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir,timestep); + } + + gotQs=true; + } + + clippedLine->deletePoint1(); + clippedLine->deletePoint2(); + delete clippedLine; + } + } + + if(gotQs) + { + { + oneEntryGotBC = true; + + std::vector<int> p(3); + p[0]=ix1; p[1]=ix2; p[2]=ix3; + transNodeIndices.insert(p); + + for(int index=(int)bcAdapters.size()-1; index>=0; --index) + bcAdapters[index]->adaptBC(*this,bc,internX1,internX2,internX3,timestep); + } + } + } + } + } + } + } + + return oneEntryGotBC; +} +////////////////////////////////////////////////////////////////////////// +void D3Q27Interactor::addQsLineSet(std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) +{ + for(SPtr<Block3D> block : bcBlocks) + { + if(!block) continue; + + double dx = grid.lock()->getDeltaX(block); + UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block); + + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + + map<SPtr<Block3D>, set< std::vector<int> > >::iterator pos = bcNodeIndicesMap.find(block); + if(pos==bcNodeIndicesMap.end()) + { + UB_THROW( UbException(UB_EXARGS,"block nicht in indizes map!!!") ); + } + set< std::vector<int> >& transNodeIndicesSet = pos->second; + set< std::vector<int> >::iterator setPos; + + std::size_t node1Index, node2Index; + + UbTupleDouble3 blockOrg = grid.lock()->getBlockWorldCoordinates(block); + + for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end(); ++setPos) + { + int ix1 = (*setPos)[0]; + int ix2 = (*setPos)[1]; + int ix3 = (*setPos)[2]; + + if(bcArray->isFluid(ix1,ix2,ix3)) //it may be that the node is replaced by another interactor e.g. was marked as solid !!! + { + if( !bcArray->hasBC(ix1,ix2,ix3) ) continue; + SPtr<BoundaryConditions> bc = bcArray->getBC(ix1,ix2,ix3); + + double x1a = val<1>(blockOrg) - val<1>(orgDelta) + ix1 * dx; + double x2a = val<2>(blockOrg) - val<2>(orgDelta) + ix2 * dx; + double x3a = val<3>(blockOrg) - val<3>(orgDelta) + ix3 * dx; + nodes.push_back( makeUbTuple( (float)x1a, (float)x2a, (float)x3a ) ); + node1Index = nodes.size()-1; + + for(int dir = D3Q27System::FSTARTDIR; dir<=D3Q27System::FENDDIR; dir++) + { + if (bc->hasBoundaryConditionFlag(D3Q27System::INVDIR[dir])) + { + double x1b, x2b, x3b, q = bc->getQ(dir); + switch(dir) + { + case D3Q27System::E : x1b = x1a+q*dx; x2b = x2a ; x3b = x3a ; break; + case D3Q27System::N : x1b = x1a ; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::W : x1b = x1a-q*dx; x2b = x2a ; x3b = x3a ; break; + case D3Q27System::S : x1b = x1a ; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::NE: x1b = x1a+q*dx; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::NW: x1b = x1a-q*dx; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::SW: x1b = x1a-q*dx; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::SE: x1b = x1a+q*dx; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::T : x1b = x1a ; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TE: x1b = x1a+q*dx; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TN: x1b = x1a ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + case D3Q27System::TW: x1b = x1a-q*dx; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TS: x1b = x1a ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::B : x1b = x1a ; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BE: x1b = x1a+q*dx; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BN: x1b = x1a ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BW: x1b = x1a-q*dx; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BS: x1b = x1a ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TNE : x1b = x1a+q*dx ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + case D3Q27System::BSW : x1b = x1a-q*dx ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BNE : x1b = x1a+q*dx ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TSW : x1b = x1a-q*dx ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::TSE : x1b = x1a+q*dx ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::BNW : x1b = x1a-q*dx ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BSE : x1b = x1a+q*dx ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TNW : x1b = x1a-q*dx ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + default: throw UbException(UB_EXARGS,"unknown direction"); + } + + nodes.push_back( makeUbTuple( (float)x1b, (float)x2b, (float)x3b ) ); + node2Index = nodes.size()-1; + + lines.push_back( makeUbTuple( (int)node1Index, (int)node2Index) ); + } + } + } + } + } +} +//////////////////////////////////////////////////////////////////////////// +vector< pair<GbPoint3D,GbPoint3D> > D3Q27Interactor::getQsLineSet() +{ + vector< pair<GbPoint3D,GbPoint3D> > QsLineSet; + pair<GbPoint3D,GbPoint3D> pointpair; + + UbTupleInt3 blocknx = grid.lock()->getBlockNX(); + + int blocknx1 = val<1>(blocknx); + int blocknx2 = val<2>(blocknx); + int blocknx3 = val<3>(blocknx); + + for(SPtr<Block3D> block : bcBlocks) + { + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<BCArray3D> bcMatrix = kernel->getBCProcessor()->getBCArray(); + UbTupleDouble3 nodeOffset = grid.lock()->getNodeOffset(block); + + //Check whether top row is double in the system or not + bool include_N_Face = false; //x1=[0..blocknx1[ && x3=[0..blocknx3[ + bool include_E_Face = false; //x2=[0..blocknx2[ && x3=[0..blocknx3[ + bool include_T_Face = false; //x1=[0..blocknx1[ && x2=[0..blocknx2[ + bool include_NE_Edge = false; //(x1/x2/x3)=(blocknx1/blocknx2/[0..blocknx3[) + bool include_TN_Edge = false; //(x1/x2/x3)=([0..blocknx1[/blocknx2/blocknx1) + bool include_TE_Edge = false; //(x1/x2/x3)=(blocknx1/[0..blocknx2[/blocknx2) + if(block) + { + if( !block->getConnector(D3Q27System::N ) ) include_N_Face = true; + if( !block->getConnector(D3Q27System::E ) ) include_E_Face = true; + if( !block->getConnector(D3Q27System::T ) ) include_T_Face = true; + if( !block->getConnector(D3Q27System::NE) && include_N_Face && include_E_Face ) include_NE_Edge = true; + if( !block->getConnector(D3Q27System::TN) && include_T_Face && include_N_Face ) include_TN_Edge = true; + if( !block->getConnector(D3Q27System::TE) && include_T_Face && include_E_Face ) include_TE_Edge = true; + } + + map<SPtr<Block3D>, set< std::vector<int> > >::iterator pos = bcNodeIndicesMap.find(block); + if(pos==bcNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!"+block->toString()); + set< std::vector<int> >& transNodeIndicesSet = pos->second; + set< std::vector<int> >::iterator setPos; + + double x1,x2,x3,dx; + grid.lock()->calcStartCoordinatesAndDelta(block,x1,x2,x3,dx); + + for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end(); ++setPos) + { + int ix1 = (*setPos)[0]; + int ix2 = (*setPos)[1]; + int ix3 = (*setPos)[2]; + + if( ( ix1<blocknx1 && ix2<blocknx2 && ix3<blocknx3 ) + || ( include_E_Face && ix1==blocknx1 && ix2<blocknx2 && ix3<blocknx3 ) + || ( include_N_Face && ix2==blocknx2 && ix1<blocknx1 && ix3<blocknx3 ) + || ( include_T_Face && ix3==blocknx3 && ix1<blocknx1 && ix2<blocknx2 ) + || ( include_NE_Edge && ix1==blocknx1 && ix2==blocknx2 ) + || ( include_TN_Edge && ix2==blocknx2 && ix3==blocknx3 ) + || ( include_TE_Edge && ix1==blocknx1 && ix3==blocknx3 ) ) + { + if(bcMatrix->isFluid(ix1,ix2,ix3)) //it may be that the node is replaced by another interactor e.g. was marked as solid !!! + { + if( !bcMatrix->hasBC(ix1,ix2,ix3) ) continue; + SPtr<BoundaryConditions> bc = bcMatrix->getBC(ix1,ix2,ix3); + double x1a = x1-val<1>(nodeOffset)+dx * ix1; + double x2a = x2-val<2>(nodeOffset)+dx * ix2; + double x3a = x3-val<3>(nodeOffset)+dx * ix3; + pointpair.first.setX1(x1a); + pointpair.first.setX2(x2a); + pointpair.first.setX3(x3a); + for(int dir = D3Q27System::FSTARTDIR; dir<=D3Q27System::FENDDIR; dir++) + { + if (bc->hasBoundaryConditionFlag(D3Q27System::INVDIR[dir])) + { + double x1b, x2b, x3b, q = bc->getQ(dir); + switch(dir) + { + case D3Q27System::E : x1b = x1a+q*dx; x2b = x2a ; x3b = x3a ; break; + case D3Q27System::N : x1b = x1a ; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::W : x1b = x1a-q*dx; x2b = x2a ; x3b = x3a ; break; + case D3Q27System::S : x1b = x1a ; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::NE: x1b = x1a+q*dx; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::NW: x1b = x1a-q*dx; x2b = x2a+q*dx; x3b = x3a ; break; + case D3Q27System::SW: x1b = x1a-q*dx; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::SE: x1b = x1a+q*dx; x2b = x2a-q*dx; x3b = x3a ; break; + case D3Q27System::T : x1b = x1a ; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TE: x1b = x1a+q*dx; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TN: x1b = x1a ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + case D3Q27System::TW: x1b = x1a-q*dx; x2b = x2a ; x3b = x3a+q*dx; break; + case D3Q27System::TS: x1b = x1a ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::B : x1b = x1a ; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BE: x1b = x1a+q*dx; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BN: x1b = x1a ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BW: x1b = x1a-q*dx; x2b = x2a ; x3b = x3a-q*dx; break; + case D3Q27System::BS: x1b = x1a ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TNE : x1b = x1a+q*dx ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + case D3Q27System::BSW : x1b = x1a-q*dx ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BNE : x1b = x1a+q*dx ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TSW : x1b = x1a-q*dx ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::TSE : x1b = x1a+q*dx ; x2b = x2a-q*dx; x3b = x3a+q*dx; break; + case D3Q27System::BNW : x1b = x1a-q*dx ; x2b = x2a+q*dx; x3b = x3a-q*dx; break; + case D3Q27System::BSE : x1b = x1a+q*dx ; x2b = x2a-q*dx; x3b = x3a-q*dx; break; + case D3Q27System::TNW : x1b = x1a-q*dx ; x2b = x2a+q*dx; x3b = x3a+q*dx; break; + default: throw UbException(UB_EXARGS,"unknown direction"); + } + pointpair.second.setX1(x1b); + pointpair.second.setX2(x2b); + pointpair.second.setX3(x3b); + QsLineSet.push_back(pointpair); + } + } + + } + } + } + } + return QsLineSet; +} + +void D3Q27Interactor::writeValidationAVSFile(string filename) +{ + UBLOG(logINFO,"D3Q27Interactor::writeValidationAVSFile("<<filename<<") - start "); + ofstream out(filename.c_str(),ios::out); + if(!out) throw UbException(UB_EXARGS,"couldn't open file "+filename); + + int numpoints, numlines; + vector< pair<GbPoint3D,GbPoint3D> > qsLineSet = this->getQsLineSet(); + numlines = (unsigned)qsLineSet.size(); + numpoints = numlines*2; + + out<<"# UCD-File created by D3Q27Interactor\n"; + out<<numpoints<<" "<<numlines<<" 0 0 0 "<<endl; + int nr=1; + for (int i=0; i<numlines; i++) + { + out<<nr++<<" "<<qsLineSet[i].first.getX1Coordinate() <<" " <<qsLineSet[i].first.getX2Coordinate() <<" " <<qsLineSet[i].first.getX3Coordinate() <<" \n"; + out<<nr++<<" "<<qsLineSet[i].second.getX1Coordinate()<<" " <<qsLineSet[i].second.getX2Coordinate()<<" " <<qsLineSet[i].second.getX3Coordinate() <<" \n"; + } + nr = 1; + for (int i=0; i<numlines; i++) + { + int el = nr+1; + out<<i+1<<" "<<2<<" line "<<nr<<" "<<el<<" "<<endl; + nr=el+1; + } + UBLOG(logINFO,"D3Q27Interactor::writeValidationAVSFile("<<filename<<") - end"); +} diff --git a/VirtualFluidsCore/Interactors/D3Q27Interactor.h b/VirtualFluidsCore/Interactors/D3Q27Interactor.h new file mode 100644 index 0000000000000000000000000000000000000000..3410a5a910a34e499d948207698925749c5f6a16 --- /dev/null +++ b/VirtualFluidsCore/Interactors/D3Q27Interactor.h @@ -0,0 +1,115 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27Interactor.h +//! \ingroup Interactor +//! \author Sören Freudiger +//! \author Sebastian Geller +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef D3Q27INTERACTOR_H +#define D3Q27INTERACTOR_H + +#include <string> +#include <vector> +#include <map> +#include <set> +#include <PointerDefinitions.h> + +#include "UbException.h" +#include "UbTuple.h" +#include "GbPoint3D.h" +#include "Interactor3D.h" +#include "D3Q27System.h" + +class BCAdapter; +class Block3D; +class Grid3D; +class GbObject3D; + +typedef std::map<SPtr<Block3D>, std::set< std::vector<int> > > BcNodeIndicesMap; +typedef std::map<SPtr<Block3D>, std::set< UbTupleInt3 > > SolidNodeIndicesMap; + +//! \brief A specialized class for grid generation. +//! \details Support standard geometric primitives. +class D3Q27Interactor : public Interactor3D +{ +public: + D3Q27Interactor(); + D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type); + D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, SPtr<BCAdapter> bcAdapter, int type); + D3Q27Interactor(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, SPtr<BCAdapter> bcAdapter, int type, Interactor3D::Accuracy a); + + virtual ~D3Q27Interactor(); + + void setRelevantForForces(const bool& value) { this->relevantForForces = value; } + bool isRelevantForForces() { return this->relevantForForces; } + + virtual void addBCAdapter(const SPtr<BCAdapter> bcAdapter) { bcAdapters.push_back(bcAdapter); } + void deleteBCAdapter() { bcAdapters.clear(); } + + + virtual void initInteractor(const double& timeStep=0); + void updateInteractor(const double& timestep=0); + + void setReinitWithStoredQs(bool reinitWithStoredQsFlag) { this->reinitWithStoredQsFlag = reinitWithStoredQsFlag; } + + void removeSolidBlocks() { Interactor3D::removeSolidBlocks(); solidNodeIndicesMap.clear(); } + void removeBcBlocks() { Interactor3D::removeBcBlocks(); bcNodeIndicesMap.clear(); } + + bool setDifferencesToGbObject3D(const SPtr<Block3D> block); + + ObObject* clone() { throw UbException(UB_EXARGS,"not implemented"); } + + + void writeValidationAVSFile(std::string filename); + virtual std::vector< std::pair<GbPoint3D,GbPoint3D> > getQsLineSet(); + + void addQsLineSet(std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines); + + const BcNodeIndicesMap& getBcNodeIndicesMap() const { return bcNodeIndicesMap; } + +protected: + bool relevantForForces; + bool reinitWithStoredQsFlag; + + std::vector<SPtr<BCAdapter> > bcAdapters; + + SolidNodeIndicesMap solidNodeIndicesMap; + BcNodeIndicesMap bcNodeIndicesMap; + + void initRayVectors(); + double rayX1[D3Q27System::FENDDIR+1]; + double rayX2[D3Q27System::FENDDIR+1]; + double rayX3[D3Q27System::FENDDIR+1]; + +}; + + +#endif diff --git a/VirtualFluidsCore/Interactors/Interactor3D.cpp b/VirtualFluidsCore/Interactors/Interactor3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7fdab60f4da5ec779b7200f26b95d61d9e42475 --- /dev/null +++ b/VirtualFluidsCore/Interactors/Interactor3D.cpp @@ -0,0 +1,346 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Interactor3D.cpp +//! \ingroup Interactor +//! \author Konstantin Kutscher +//======================================================================================= + +#include "Interactor3D.h" + +#include <fstream> +#include <geometry3d/GbCuboid3D.h> +#include <basics/utilities/UbMath.h> +#include "UbException.h" + +#include "Grid3D.h" +#include "Block3D.h" +#include "GbObject3D.h" + + +using namespace std; + +const int Interactor3D::SOLID = (1<<0); //1 +const int Interactor3D::INVERSESOLID = (1<<1); //2 +const int Interactor3D::TIMEDEPENDENT = (1<<2); //4 //zeitlich +const int Interactor3D::FLUID = (1<<3); //8 +const int Interactor3D::MOVEABLE = (1<<4); //16 // geometrisch +const int Interactor3D::CHANGENOTNECESSARY = (1<<5); //32 + + + +////////////////////////////////////////////////////////////////////////// +Interactor3D::Interactor3D() + : type(SOLID) +{ + +} +////////////////////////////////////////////////////////////////////////// +Interactor3D::Interactor3D(SPtr<Grid3D> grid, int type) + : type(type) + , grid(grid) +{ + +} +////////////////////////////////////////////////////////////////////////// +Interactor3D::Interactor3D(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type) + : geoObject3D(geoObject3D) + , grid(grid) + , type(type) + , accuracy(SIMPLE) +{ + +} +////////////////////////////////////////////////////////////////////////// +Interactor3D::Interactor3D(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type, Interactor3D::Accuracy a) + : geoObject3D(geoObject3D) + , grid(grid) + , type(type) + , accuracy(a) +{ + +} +////////////////////////////////////////////////////////////////////////// +Interactor3D::~Interactor3D() +{ +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::arePointsInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + bool result = true; + for (double ix3=minX3; ix3<=maxX3; ix3+=delta) + for (double ix2=minX2; ix2<=maxX2; ix2+=delta) + for (double ix1=minX1; ix1<=maxX1; ix1+=delta) + result = result && this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3); + + return result; +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::arePointsOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + bool result = true; + for (double ix3=minX3; ix3<=maxX3; ix3+=delta) + for (double ix2=minX2; ix2<=maxX2; ix2+=delta) + for (double ix1=minX1; ix1<=maxX1; ix1+=delta) + result = result && (!this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3)); + + return result; +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::arePointsCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + bool result = true; + for (double ix3=minX3; ix3<=maxX3; ix3+=delta) + for (double ix2=minX2; ix2<=maxX2; ix2+=delta) + for (double ix1=minX1; ix1<=maxX1; ix1+=delta) + result = result || this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3); + + return result; +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::isBlockOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + switch (accuracy) + { + //simple duff + case SIMPLE: + return !this->geoObject3D->isCellInsideOrCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3); + //test only edges + case EDGES: + return arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) && + arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) && + arePointsOutsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) && + + arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) && + arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) && + arePointsOutsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) && + + arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) && + arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) && + arePointsOutsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta); + //test only faces + case FACES: + return arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) && + arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) && + arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta); + //test all points + case POINTS: + return arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta); + default: + UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") ); + break; + } +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::isBlockInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + switch (accuracy) + { + //simple duff + case SIMPLE: + return this->geoObject3D->isCellInsideGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3); + //test only edges + case EDGES: + return arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) && + arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) && + arePointsInsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) && + + arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) && + arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) && + arePointsInsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) && + + arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) && + arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) && + arePointsInsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta); + //test only faces + case FACES: + return arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) && + arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) && + arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) && + arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) && + arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta); + //test all points + case POINTS: + return arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta); + default: + UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") ); + break; + } +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::isBlockCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta) +{ + switch (accuracy) + { + //simple duff + case SIMPLE: + return this->geoObject3D->isCellCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3); + //test only edges + case EDGES: + return arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) || + arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) || + arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) || + arePointsCuttingGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) || + + arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) || + arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) || + arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) || + arePointsCuttingGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) || + + arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) || + arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) || + arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) || + arePointsCuttingGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta); + //test only faceCutting + case FACES: + return arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) || + arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) || + arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) || + arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) || + arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) || + arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta); + //test all pointCutting + case POINTS: + return arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta); + default: + UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") ); + break; + } +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::setSolidBlock(SPtr<Block3D> block) +{ + double minX1,minX2,minX3,maxX1,maxX2,maxX3; + + double deltaX = grid.lock()->getDeltaX(block); + UbTupleDouble3 blockLengths = grid.lock()->getBlockLengths(block); + UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block); + UbTupleDouble3 nodeOffset = grid.lock()->getNodeOffset(block); + + //coordinates of block without ghost layer + minX1 = val<1>(org) + val<1>(nodeOffset); + minX2 = val<2>(org) + val<2>(nodeOffset); + minX3 = val<3>(org) + val<3>(nodeOffset); + maxX1 = val<1>(org) + val<1>(blockLengths) - val<1>(nodeOffset); + maxX2 = val<2>(org) + val<2>(blockLengths) - val<2>(nodeOffset); + maxX3 = val<3>(org) + val<3>(blockLengths) - val<3>(nodeOffset); + + if(this->isInverseSolid()) + { + if(isBlockOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX)) + { + block->setActive(false); + this->solidBlocks.push_back(block); + } + } + else //solid + { + if(isBlockInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX)) + { + block->setActive(false); + this->solidBlocks.push_back(block); + } + } +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::setBCBlock(SPtr<Block3D> block) +{ + double minX1,minX2,minX3,maxX1,maxX2,maxX3; + + double deltaX = grid.lock()->getDeltaX(block); + UbTupleDouble3 blockLengths = grid.lock()->getBlockLengths(block); + UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block); + UbTupleDouble3 nodeOffset = grid.lock()->getNodeOffset(block); + + //coordinates of block with ghost layer + minX1 = val<1>(org) - val<1>(nodeOffset); + minX2 = val<2>(org) - val<2>(nodeOffset); + minX3 = val<3>(org) - val<3>(nodeOffset); + maxX1 = val<1>(org) + val<1>(blockLengths) + val<1>(nodeOffset); + maxX2 = val<2>(org) + val<2>(blockLengths) + val<2>(nodeOffset); + maxX3 = val<3>(org) + val<3>(blockLengths) + val<3>(nodeOffset); + + if(isBlockCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX)) + this->bcBlocks.push_back(block); +} + +UbTupleDouble3 Interactor3D::getForces() +{ + UB_THROW( UbException("UbTupleDouble3 getForces() - gehoert in die abgeleitete klasse") ); +} +void Interactor3D::setID(int id) +{ + this->id = id; +} +////////////////////////////////////////////////////////////////////////// +int Interactor3D::getID() +{ + return id; +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::setActive() +{ + active = true; +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::setInactive() +{ + active = false; +} +////////////////////////////////////////////////////////////////////////// +bool Interactor3D::isActive() +{ + return active; +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::initInteractor(const double& timeStep) +{ + //UBLOG(logINFO, "transBlocks.size = "<<transBlocks.size()); + + for(SPtr<Block3D> block : bcBlocks) + { + this->setDifferencesToGbObject3D(block); + } +} +////////////////////////////////////////////////////////////////////////// +void Interactor3D::updateInteractor(const double& timeStep) +{ + UB_THROW( UbException("Interactor3D::updateInteractor - toDo") ); +} +////////////////////////////////////////////////////////////////////////// + diff --git a/VirtualFluidsCore/Interactors/Interactor3D.h b/VirtualFluidsCore/Interactors/Interactor3D.h new file mode 100644 index 0000000000000000000000000000000000000000..56390b18caa29810606a964700460afc3428422d --- /dev/null +++ b/VirtualFluidsCore/Interactors/Interactor3D.h @@ -0,0 +1,146 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Interactor3D.h +//! \ingroup Interactor +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef INTERACTOR3D_H +#define INTERACTOR3D_H + +#include <vector> +#include <PointerDefinitions.h> + +#include "UbSystem.h" +#include "UbTuple.h" + +class Block3D; +class Grid3D; +class GbObject3D; + +//! A base class for grid generation. +class Interactor3D : public enableSharedFromThis<Interactor3D> +{ +public: + enum Accuracy{SIMPLE, EDGES, FACES, POINTS}; + Interactor3D(); + Interactor3D(SPtr<Grid3D> grid, int type=Interactor3D::SOLID); + Interactor3D(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type); + //! constructor + //! \param a set accuracy for arePointsInObject() and arePointsNotInObject() + Interactor3D(SPtr<GbObject3D> geoObject3D, SPtr<Grid3D> grid, int type, Interactor3D::Accuracy a); + + virtual ~Interactor3D(); + virtual void initInteractor(const double& timestep=0); + virtual void updateInteractor(const double& timestep=0)=0; + + void setSolidBlock(SPtr<Block3D> block); + void setBCBlock(SPtr<Block3D> block); + + virtual UbTupleDouble3 getForces(); + + void setSolid() { UbSystem::setBit(this->type, SOLID ); } + void setMoveable() { UbSystem::setBit(this->type, MOVEABLE); } + + bool isSolid() { return UbSystem::bitCheck(this->type, SOLID ); } + bool isInverseSolid() { return UbSystem::bitCheck(this->type, INVERSESOLID ); } + bool isTimeDependent() { return UbSystem::bitCheck(this->type, TIMEDEPENDENT); } + bool isMoveable() { return UbSystem::bitCheck(this->type, MOVEABLE ); } + + SPtr<Grid3D> getGrid3D() const { return grid.lock(); } + void setGrid3D(SPtr<Grid3D> grid) { this->grid = grid; } + virtual SPtr<GbObject3D> getGbObject3D() const { return geoObject3D; } + virtual bool setDifferencesToGbObject3D(const SPtr<Block3D> block/*, const double& x1, const double& x2, const double& x3, const double& blockLengthX1, const double& blockLengthX2, const double& blockLengthX3, const double& timestep=0*/) + { + //UBLOG(logINFO, "Interactor3D::setDifferencesToGbObject3D()"); + return false; + } + + virtual std::vector<SPtr<Block3D> >& getBcBlocks() { return this->bcBlocks; } + virtual void removeBcBlocks() { this->bcBlocks.clear(); } + virtual std::vector<SPtr<Block3D> >& getSolidBlockSet() { return this->solidBlocks; } + virtual void removeSolidBlocks() { this->solidBlocks.clear(); } + + void setID(int id); + int getID(); + + void setActive(); + void setInactive(); + bool isActive(); + +protected: + void setTimeDependent() { UbSystem::setBit(this->type , TIMEDEPENDENT); } + void unsetTimeDependent() { UbSystem::unsetBit(this->type, TIMEDEPENDENT); } + + //! detect that points are inside object + //! \param min/max coordinates of bounding box + //! \param delta is delta x + bool arePointsInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + + //! detect that points aren't inside object + //! \param min/max coordinates of bounding box + //! \param delta is delta x + bool arePointsOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + + //! detect that points are cutting object + //! \param min/max coordinates of bounding box + //! \param delta is delta x + bool arePointsCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + + bool isBlockOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + bool isBlockInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + bool isBlockCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta); + + int type; + + WPtr<Grid3D> grid; + SPtr<GbObject3D> geoObject3D; + + std::vector<SPtr<Block3D> > bcBlocks; + std::vector<SPtr<Block3D> > solidBlocks; + int accuracy; + + bool active; + int id; + +public: + static const int SOLID ;//= (1<<0); //1 + static const int INVERSESOLID ;//= (1<<1); //2 + static const int TIMEDEPENDENT ;//= (1<<2); //4 //zeitlich + static const int FLUID ;//= (1<<3); //8 + static const int MOVEABLE ;//= (1<<4); //16 // geometrisch + static const int CHANGENOTNECESSARY ;//= (1<<5); //32 + +private: + +}; + + + +#endif diff --git a/VirtualFluidsCore/Interactors/InteractorsHelper.cpp b/VirtualFluidsCore/Interactors/InteractorsHelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff6fe730cae27dc2ce08690096a1c51bfb54a01d --- /dev/null +++ b/VirtualFluidsCore/Interactors/InteractorsHelper.cpp @@ -0,0 +1,78 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InteractorsHelper.cpp +//! \ingroup Interactor +//! \author Konstantin Kutscher +//======================================================================================= + +#include "InteractorsHelper.h" + +#include <Grid3DVisitor.h> +#include <Grid3D.h> +#include <Interactor3D.h> +#include "Block3D.h" +#include "SetSolidBlocksBlockVisitor.h" +#include "SetBcBlocksBlockVisitor.h" + + +InteractorsHelper::InteractorsHelper(SPtr<Grid3D> grid) :grid(grid) +{ + +} +////////////////////////////////////////////////////////////////////////// +InteractorsHelper::~InteractorsHelper() +{ + +} +////////////////////////////////////////////////////////////////////////// +void InteractorsHelper::addInteractor( SPtr<Interactor3D> interactor ) +{ + interactors.push_back(interactor); +} +////////////////////////////////////////////////////////////////////////// +void InteractorsHelper::setBC() +{ + for(SPtr<Interactor3D> i : interactors) + i->initInteractor(); +} +////////////////////////////////////////////////////////////////////////// +void InteractorsHelper::selectBlocks() +{ + setBcBlocks(); +} +////////////////////////////////////////////////////////////////////////// +void InteractorsHelper::setBcBlocks() +{ + for(const SPtr<Interactor3D> interactor : interactors) + { + SetBcBlocksBlockVisitor v(interactor); + grid->accept(v); + } +} + diff --git a/VirtualFluidsCore/Interactors/InteractorsHelper.h b/VirtualFluidsCore/Interactors/InteractorsHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..29ed01a16432fb1080d01735d67aafcea46ee38c --- /dev/null +++ b/VirtualFluidsCore/Interactors/InteractorsHelper.h @@ -0,0 +1,66 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InteractorsHelper.h +//! \ingroup Interactor +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef InteractorsHelper_h +#define InteractorsHelper_h + +#include <vector> +#include <PointerDefinitions.h> + + +class Interactor3D; +class Block3D; +class Grid3D; +class Grid3DVisitor; + +//! A helper class for grid generation. +class InteractorsHelper +{ +public: + InteractorsHelper(SPtr<Grid3D> grid); + ~InteractorsHelper(); + + void addInteractor(SPtr<Interactor3D> interactor); + void selectBlocks(); + void setBC(); +protected: + void setBcBlocks(); +private: + std::vector<SPtr<Interactor3D> > interactors; + SPtr<Grid3D> grid; + std::vector<SPtr<Block3D> > solidBlocks; + SPtr<Grid3DVisitor> visitor; + bool deleteBlocks; +}; + +#endif diff --git a/VirtualFluidsCore/LBM/CMakePackage.txt b/VirtualFluidsCore/LBM/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/LBM/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/LBM/CumulantK17LBMKernel.cpp b/VirtualFluidsCore/LBM/CumulantK17LBMKernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79f0a586ad946cdf1624b8d915318006a0a7d24c --- /dev/null +++ b/VirtualFluidsCore/LBM/CumulantK17LBMKernel.cpp @@ -0,0 +1,648 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CumulantK17LBMKernel.cpp +//! \ingroup LBM +//! \author Konstantin Kutscher, Martin Geier +//======================================================================================= + +#include "CumulantK17LBMKernel.h" +#include "D3Q27System.h" +#include "D3Q27EsoTwist3DSplittedVector.h" +#include <math.h> +#include "DataSet3D.h" +#include "LBMKernel.h" +#include "Block3D.h" +#include "BCArray3D.h" + +#define PROOF_CORRECTNESS + +using namespace UbMath; + +////////////////////////////////////////////////////////////////////////// +CumulantK17LBMKernel::CumulantK17LBMKernel() +{ + this->compressible = true; +} +////////////////////////////////////////////////////////////////////////// +CumulantK17LBMKernel::~CumulantK17LBMKernel(void) +{ + +} +////////////////////////////////////////////////////////////////////////// +void CumulantK17LBMKernel::initDataSet() +{ + SPtr<DistributionArray3D> d(new D3Q27EsoTwist3DSplittedVector(nx[0] + 2, nx[1] + 2, nx[2] + 2, -999.9)); + dataSet->setFdistributions(d); +} +////////////////////////////////////////////////////////////////////////// +SPtr<LBMKernel> CumulantK17LBMKernel::clone() +{ + SPtr<LBMKernel> kernel(new CumulantK17LBMKernel()); + kernel->setNX(nx); + std::dynamic_pointer_cast<CumulantK17LBMKernel>(kernel)->initDataSet(); + kernel->setCollisionFactor(this->collFactor); + kernel->setBCProcessor(bcProcessor->clone(kernel)); + kernel->setWithForcing(withForcing); + kernel->setForcingX1(muForcingX1); + kernel->setForcingX2(muForcingX2); + kernel->setForcingX3(muForcingX3); + kernel->setIndex(ix1, ix2, ix3); + kernel->setDeltaT(deltaT); + kernel->setBlock(block.lock()); + + return kernel; +} +////////////////////////////////////////////////////////////////////////// +void CumulantK17LBMKernel::calculate(int step) +{ + ////////////////////////////////////////////////////////////////////////// + //! Cumulant K17 Kernel is based on + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! and + //! <a href="https://doi.org/10.1016/j.jcp.2017.07.004"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.07.004 ]</b></a> + //! + //! The cumulant kernel is executed in the following steps + //! + //////////////////////////////////////////////////////////////////////////////// + //! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim. + //! + using namespace D3Q27System; + using namespace std; + + //initializing of forcing stuff + if (withForcing) + { + muForcingX1.DefineVar("x1", &muX1); muForcingX1.DefineVar("x2", &muX2); muForcingX1.DefineVar("x3", &muX3); + muForcingX2.DefineVar("x1", &muX1); muForcingX2.DefineVar("x2", &muX2); muForcingX2.DefineVar("x3", &muX3); + muForcingX3.DefineVar("x1", &muX1); muForcingX3.DefineVar("x2", &muX2); muForcingX3.DefineVar("x3", &muX3); + + muDeltaT = deltaT; + + muForcingX1.DefineVar("dt", &muDeltaT); + muForcingX2.DefineVar("dt", &muDeltaT); + muForcingX3.DefineVar("dt", &muDeltaT); + + muNu = (1.0 / 3.0) * (1.0 / collFactor - 1.0 / 2.0); + + muForcingX1.DefineVar("nu", &muNu); + muForcingX2.DefineVar("nu", &muNu); + muForcingX3.DefineVar("nu", &muNu); + + LBMReal forcingX1 = 0; + LBMReal forcingX2 = 0; + LBMReal forcingX3 = 0; + } + ///////////////////////////////////// + + localDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions(); + nonLocalDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions(); + restDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions(); + + SPtr<BCArray3D> bcArray = this->getBCProcessor()->getBCArray(); + + const int bcArrayMaxX1 = (int)bcArray->getNX1(); + const int bcArrayMaxX2 = (int)bcArray->getNX2(); + const int bcArrayMaxX3 = (int)bcArray->getNX3(); + + int minX1 = ghostLayerWidth; + int minX2 = ghostLayerWidth; + int minX3 = ghostLayerWidth; + int maxX1 = bcArrayMaxX1 - ghostLayerWidth; + int maxX2 = bcArrayMaxX2 - ghostLayerWidth; + int maxX3 = bcArrayMaxX3 - ghostLayerWidth; + + LBMReal omega = collFactor; + + for (int x3 = minX3; x3 < maxX3; x3++) + { + for (int x2 = minX2; x2 < maxX2; x2++) + { + for (int x1 = minX1; x1 < maxX1; x1++) + { + if (!bcArray->isSolid(x1, x2, x3) && !bcArray->isUndefined(x1, x2, x3)) + { + int x1p = x1 + 1; + int x2p = x2 + 1; + int x3p = x3 + 1; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on timestep is based on the esoteric twist algorithm + //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + + //E N T + //c c c + ////////// + //W S B + //a a a + + //Rest is b + + //mfxyz + //a - negative + //b - null + //c - positive + + // a b c + //-1 0 1 + + LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1, x2, x3); + LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N, x1, x2, x3); + LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T, x1, x2, x3); + LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE, x1, x2, x3); + LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW, x1p, x2, x3); + LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE, x1, x2, x3); + LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1p, x2, x3); + LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN, x1, x2, x3); + LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS, x1, x2p, x3); + LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE, x1, x2, x3); + LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW, x1p, x2, x3); + LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE, x1, x2p, x3); + LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW, x1p, x2p, x3); + + LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W, x1p, x2, x3); + LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S, x1, x2p, x3); + LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B, x1, x2, x3p); + LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW, x1p, x2p, x3); + LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE, x1, x2p, x3); + LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW, x1p, x2, x3p); + LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE, x1, x2, x3p); + LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS, x1, x2p, x3p); + LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN, x1, x2, x3p); + LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW, x1p, x2p, x3p); + LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE, x1, x2p, x3p); + LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1p, x2, x3p); + LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3p); + + LBMReal mfbbb = (*this->restDistributions)(x1, x2, x3); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Calculate density and velocity using pyramid summation for low round-off errors as in Eq. (J1)-(J3) + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + LBMReal drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) + + (((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) + ((mfacb + mfcab) + (mfaab + mfccb))) + + ((mfabb + mfcbb) + (mfbab + mfbcb)) + (mfbba + mfbbc)) + mfbbb; + + LBMReal rho = c1 + drho; + LBMReal OOrho = c1 / rho; + //////////////////////////////////////////////////////////////////////////////////// + LBMReal vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) + + (((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) + + (mfcbb - mfabb)) / rho; + LBMReal vvy = ((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) + + (((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) + + (mfbcb - mfbab)) / rho; + LBMReal vvz = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) + + (((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) + + (mfbbc - mfbba)) / rho; + //////////////////////////////////////////////////////////////////////////////////// + //forcing + /////////////////////////////////////////////////////////////////////////////////////////// + if (withForcing) + { + muX1 = static_cast<double>(x1 - 1 + ix1 * maxX1); + muX2 = static_cast<double>(x2 - 1 + ix2 * maxX2); + muX3 = static_cast<double>(x3 - 1 + ix3 * maxX3); + + forcingX1 = muForcingX1.Eval(); + forcingX2 = muForcingX2.Eval(); + forcingX3 = muForcingX3.Eval(); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Add half of the acceleration (body force) to the velocity as in Eq. (42) + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + vvx += forcingX1 * deltaT * c1o2; // X + vvy += forcingX2 * deltaT * c1o2; // Y + vvz += forcingX3 * deltaT * c1o2; // Z + } + /////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////// + LBMReal oMdrho = c1; + //////////////////////////////////////////////////////////////////////////////////// + // calculate the square of velocities for this lattice node + LBMReal vx2 = vvx * vvx; + LBMReal vy2 = vvy * vvy; + LBMReal vz2 = vvz * vvz; + //////////////////////////////////////////////////////////////////////////////////// + //! - Set relaxation limiters for third order cumulants to default value \f$ \lambda=0.001 \f$ according to section 6 in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + LBMReal wadjust; + LBMReal qudricLimitP = c1o100; + LBMReal qudricLimitM = c1o100; + LBMReal qudricLimitD = c1o100; + //////////////////////////////////////////////////////////////////////////////////// + //! - Chimera transform from well conditioned distributions to central moments as defined in Appendix J in + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! see also Eq. (6)-(14) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////////////// + // Z - Dir + forwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9); + forwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36, c1o36); + + //////////////////////////////////////////////////////////////////////////////////// + // Y - Dir + forwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6, c1o6); + forwardChimera(mfaab, mfabb, mfacb, vvy, vy2); + forwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18, c1o18); + forwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3); + forwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2); + forwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9); + forwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6, c1o6); + forwardChimera(mfcab, mfcbb, mfccb, vvy, vy2); + forwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18, c1o18); + + //////////////////////////////////////////////////////////////////////////////////// + // X - Dir + forwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1, c1); + forwardChimera(mfaba, mfbba, mfcba, vvx, vx2); + forwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3, c1o3); + forwardChimera(mfaab, mfbab, mfcab, vvx, vx2); + forwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2); + forwardChimera(mfacb, mfbcb, mfccb, vvx, vx2); + forwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3, c1o3); + forwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2); + forwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9, c1o9); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and equations according to + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! => [NAME IN PAPER]=[NAME IN CODE]=[DEFAULT VALUE]. + //! - Trace of second order cumulants \f$ C_{200}+C_{020}+C_{002} \f$ used to adjust bulk viscosity:\f$\omega_2=OxxPyyPzz=1.0 \f$. + //! - Third order cumulants \f$ C_{120}+C_{102} \f$, \f$ C_{210}+C_{012} \f$, \f$ C_{201}+C_{021} \f$: \f$\omega_3=OxyyPxzz\f$ set according to Eq. (111) with simplifications assuming \f$\omega_2=1.0\f$. + //! - Third order cumulants \f$ C_{120}-C_{102} \f$, \f$ C_{210}-C_{012} \f$, \f$ C_{201}-C_{021} \f$: \f$\omega_4 = OxyyMxzz\f$ set according to Eq. (112) with simplifications assuming \f$\omega_2 = 1.0\f$. + //! - Third order cumulants \f$ C_{111} \f$: \f$\omega_5 = Oxyz\f$ set according to Eq. (113) with simplifications assuming \f$\omega_2 = 1.0\f$ (modify for different bulk viscosity). + //! - Fourth order cumulants \f$ C_{220} \f$, \f$ C_{202} \f$, \f$ C_{022} \f$, \f$ C_{211} \f$, \f$ C_{121} \f$, \f$ C_{112} \f$: for simplification all set to the same default value \f$ \omega_6=\omega_7=\omega_8=O4=1.0 \f$. + //! - Fifth order cumulants \f$ C_{221}\f$, \f$C_{212}\f$, \f$C_{122}\f$: \f$\omega_9=O5=1.0\f$. + //! - Sixth order cumulant \f$ C_{222}\f$: \f$\omega_{10}=O6=1.0\f$. + //! + //////////////////////////////////////////////////////////// + //2. + LBMReal OxxPyyPzz = c1; + //////////////////////////////////////////////////////////// + //3. + LBMReal OxyyPxzz = c8 * (-c2 + omega) * ( c1 + c2*omega) / (-c8 - c14*omega + c7*omega*omega); + LBMReal OxyyMxzz = c8 * (-c2 + omega) * (-c7 + c4*omega) / (c56 - c50*omega + c9*omega*omega); + LBMReal Oxyz = c24 * (-c2 + omega) * (-c2 - c7*omega + c3*omega*omega) / (c48 + c152*omega - c130*omega*omega + c29*omega*omega*omega); + //////////////////////////////////////////////////////////// + //4. + LBMReal O4 = c1; + //////////////////////////////////////////////////////////// + //5. + LBMReal O5 = c1; + //////////////////////////////////////////////////////////// + //6. + LBMReal O6 = c1; + + //////////////////////////////////////////////////////////////////////////////////// + //! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! with simplifications assuming \f$\omega_2 = 1.0\f$ (modify for different bulk viscosity). + //! + LBMReal A = (c4 + c2*omega - c3*omega*omega) / (c2 - c7*omega + c5*omega*omega); + LBMReal B = (c4 + c28*omega - c14*omega*omega) / (c6 - c21*omega + c15*omega*omega); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute cumulants from central moments according to Eq. (20)-(23) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////// + //4. + LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + c2 * mfbba * mfbab) * OOrho; + LBMReal CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + c2 * mfbba * mfabb) * OOrho; + LBMReal CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + c2 * mfbab * mfabb) * OOrho; + + LBMReal CUMcca = mfcca - (((mfcaa * mfaca + c2 * mfbba * mfbba) + c1o3 * (mfcaa + mfaca)) * OOrho - c1o9 * (drho * OOrho)); + LBMReal CUMcac = mfcac - (((mfcaa * mfaac + c2 * mfbab * mfbab) + c1o3 * (mfcaa + mfaac)) * OOrho - c1o9 * (drho * OOrho)); + LBMReal CUMacc = mfacc - (((mfaac * mfaca + c2 * mfabb * mfabb) + c1o3 * (mfaac + mfaca)) * OOrho - c1o9 * (drho * OOrho)); + //////////////////////////////////////////////////////////// + //5. + LBMReal CUMbcc = mfbcc - ((mfaac * mfbca + mfaca * mfbac + c4 * mfabb * mfbbb + c2 * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac)) * OOrho; + LBMReal CUMcbc = mfcbc - ((mfaac * mfcba + mfcaa * mfabc + c4 * mfbab * mfbbb + c2 * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc)) * OOrho; + LBMReal CUMccb = mfccb - ((mfcaa * mfacb + mfaca * mfcab + c4 * mfbba * mfbbb + c2 * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab)) * OOrho; + //////////////////////////////////////////////////////////// + //6. + LBMReal CUMccc = mfccc + ((-c4 * mfbbb * mfbbb + - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) + - c4 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) + - c2 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * OOrho + + (c4 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) + + c2 * (mfcaa * mfaca * mfaac) + + c16 * mfbba * mfbab * mfabb) * OOrho * OOrho + - c1o3 * (mfacc + mfcac + mfcca) * OOrho + - c1o9 * (mfcaa + mfaca + mfaac) * OOrho + + (c2 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) + + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) * OOrho * OOrho * c2o3 + + c1o27 * ((drho * drho - drho) * OOrho * OOrho)); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute linear combinations of second and third order cumulants + //! + //////////////////////////////////////////////////////////// + //2. + LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac; + LBMReal mxxMyy = mfcaa - mfaca; + LBMReal mxxMzz = mfcaa - mfaac; + //////////////////////////////////////////////////////////// + //3. + LBMReal mxxyPyzz = mfcba + mfabc; + LBMReal mxxyMyzz = mfcba - mfabc; + + LBMReal mxxzPyyz = mfcab + mfacb; + LBMReal mxxzMyyz = mfcab - mfacb; + + LBMReal mxyyPxzz = mfbca + mfbac; + LBMReal mxyyMxzz = mfbca - mfbac; + + //////////////////////////////////////////////////////////////////////////////////// + //incl. correction + //////////////////////////////////////////////////////////// + //! - Compute velocity gradients from second order cumulants according to Eq. (27)-(32) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! Further explanations of the correction in viscosity in Appendix H of + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! Note that the division by rho is omitted here as we need rho times the gradients later. + //! + LBMReal Dxy = -c3 * omega * mfbba; + LBMReal Dxz = -c3 * omega * mfbab; + LBMReal Dyz = -c3 * omega * mfabb; + LBMReal dxux = c1o2 * (-omega) * (mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz * (mfaaa - mxxPyyPzz); + LBMReal dyuy = dxux + omega * c3o2 * mxxMyy; + LBMReal dzuz = dxux + omega * c3o2 * mxxMzz; + //////////////////////////////////////////////////////////// + //! - Relaxation of second order cumulants with correction terms according to Eq. (33)-(35) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + mxxPyyPzz += OxxPyyPzz * (mfaaa - mxxPyyPzz) - c3 * (c1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz); + mxxMyy += omega * (-mxxMyy) - c3 * (c1 + c1o2 * (-omega)) * (vx2 * dxux - vy2 * dyuy); + mxxMzz += omega * (-mxxMzz) - c3 * (c1 + c1o2 * (-omega)) * (vx2 * dxux - vz2 * dzuz); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////no correction + //mxxPyyPzz += OxxPyyPzz*(mfaaa - mxxPyyPzz); + //mxxMyy += -(-omega) * (-mxxMyy); + //mxxMzz += -(-omega) * (-mxxMzz); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + mfabb += omega * (-mfabb); + mfbab += omega * (-mfbab); + mfbba += omega * (-mfbba); + + //////////////////////////////////////////////////////////////////////////////////// + //relax + ////////////////////////////////////////////////////////////////////////// + // incl. limiter + //! - Relaxation of third order cumulants including limiter according to Eq. (116)-(123) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + wadjust = Oxyz + (c1 - Oxyz) * abs(mfbbb) / (abs(mfbbb) + qudricLimitD); + mfbbb += wadjust * (-mfbbb); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxxyPyzz) / (abs(mxxyPyzz) + qudricLimitP); + mxxyPyzz += wadjust * (-mxxyPyzz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxxyMyzz) / (abs(mxxyMyzz) + qudricLimitM); + mxxyMyzz += wadjust * (-mxxyMyzz); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxxzPyyz) / (abs(mxxzPyyz) + qudricLimitP); + mxxzPyyz += wadjust * (-mxxzPyyz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxxzMyyz) / (abs(mxxzMyyz) + qudricLimitM); + mxxzMyyz += wadjust * (-mxxzMyyz); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxyyPxzz) / (abs(mxyyPxzz) + qudricLimitP); + mxyyPxzz += wadjust * (-mxyyPxzz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxyyMxzz) / (abs(mxyyMxzz) + qudricLimitM); + mxyyMxzz += wadjust * (-mxyyMxzz); + ////////////////////////////////////////////////////////////////////////// + // no limiter + //mfbbb += OxyyMxzz * (-mfbbb); + //mxxyPyzz += OxyyPxzz * (-mxxyPyzz); + //mxxyMyzz += OxyyMxzz * (-mxxyMyzz); + //mxxzPyyz += OxyyPxzz * (-mxxzPyyz); + //mxxzMyyz += OxyyMxzz * (-mxxzMyyz); + //mxyyPxzz += OxyyPxzz * (-mxyyPxzz); + //mxyyMxzz += OxyyMxzz * (-mxyyMxzz); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute inverse linear combinations of second and third order cumulants + //! + mfcaa = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz); + mfaca = c1o3 * (-c2 * mxxMyy + mxxMzz + mxxPyyPzz); + mfaac = c1o3 * (mxxMyy - c2 * mxxMzz + mxxPyyPzz); + + mfcba = (mxxyMyzz + mxxyPyzz) * c1o2; + mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2; + mfcab = (mxxzMyyz + mxxzPyyz) * c1o2; + mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2; + mfbca = (mxyyMxzz + mxyyPxzz) * c1o2; + mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + //4. + // no limiter + //! - Relax fourth order cumulants to modified equilibrium for fourth order convergence of diffusion according to Eq. (43)-(48) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + CUMacc = -O4 * (c1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * A + (c1 - O4) * (CUMacc); + CUMcac = -O4 * (c1 / omega - c1o2) * (dxux + dzuz) * c2o3 * A + (c1 - O4) * (CUMcac); + CUMcca = -O4 * (c1 / omega - c1o2) * (dyuy + dxux) * c2o3 * A + (c1 - O4) * (CUMcca); + CUMbbc = -O4 * (c1 / omega - c1o2) * Dxy * c1o3 * B + (c1 - O4) * (CUMbbc); + CUMbcb = -O4 * (c1 / omega - c1o2) * Dxz * c1o3 * B + (c1 - O4) * (CUMbcb); + CUMcbb = -O4 * (c1 / omega - c1o2) * Dyz * c1o3 * B + (c1 - O4) * (CUMcbb); + + ////////////////////////////////////////////////////////////////////////// + //5. + CUMbcc += O5 * (-CUMbcc); + CUMcbc += O5 * (-CUMcbc); + CUMccb += O5 * (-CUMccb); + + ////////////////////////////////////////////////////////////////////////// + //6. + CUMccc += O6 * (-CUMccc); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute central moments from post collision cumulants according to Eq. (53)-(56) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + + ////////////////////////////////////////////////////////////////////////// + //4. + mfcbb = CUMcbb + c1o3 * ((c3 * mfcaa + c1) * mfabb + c6 * mfbba * mfbab) * OOrho; + mfbcb = CUMbcb + c1o3 * ((c3 * mfaca + c1) * mfbab + c6 * mfbba * mfabb) * OOrho; + mfbbc = CUMbbc + c1o3 * ((c3 * mfaac + c1) * mfbba + c6 * mfbab * mfabb) * OOrho; + + mfcca = CUMcca + (((mfcaa * mfaca + c2 * mfbba * mfbba) * c9 + c3 * (mfcaa + mfaca)) * OOrho - (drho * OOrho)) * c1o9; + mfcac = CUMcac + (((mfcaa * mfaac + c2 * mfbab * mfbab) * c9 + c3 * (mfcaa + mfaac)) * OOrho - (drho * OOrho)) * c1o9; + mfacc = CUMacc + (((mfaac * mfaca + c2 * mfabb * mfabb) * c9 + c3 * (mfaac + mfaca)) * OOrho - (drho * OOrho)) * c1o9; + + ////////////////////////////////////////////////////////////////////////// + //5. + mfbcc = CUMbcc + c1o3 * (c3 * (mfaac * mfbca + mfaca * mfbac + c4 * mfabb * mfbbb + c2 * (mfbab * mfacb + mfbba * mfabc)) + (mfbca + mfbac)) * OOrho; + mfcbc = CUMcbc + c1o3 * (c3 * (mfaac * mfcba + mfcaa * mfabc + c4 * mfbab * mfbbb + c2 * (mfabb * mfcab + mfbba * mfbac)) + (mfcba + mfabc)) * OOrho; + mfccb = CUMccb + c1o3 * (c3 * (mfcaa * mfacb + mfaca * mfcab + c4 * mfbba * mfbbb + c2 * (mfbab * mfbca + mfabb * mfcba)) + (mfacb + mfcab)) * OOrho; + + ////////////////////////////////////////////////////////////////////////// + //6. + mfccc = CUMccc - ((-c4 * mfbbb * mfbbb + - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) + - c4 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) + - c2 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * OOrho + + (c4 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) + + c2 * (mfcaa * mfaca * mfaac) + + c16 * mfbba * mfbab * mfabb) * OOrho * OOrho + - c1o3 * (mfacc + mfcac + mfcca) * OOrho + - c1o9 * (mfcaa + mfaca + mfaac) * OOrho + + (c2 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) + + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) * OOrho * OOrho * c2o3 + + c1o27 * ((drho * drho - drho) * OOrho * OOrho)); + + + //////////////////////////////////////////////////////////////////////////////////// + //! - Add acceleration (body force) to first order cumulants according to Eq. (85)-(87) in + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + mfbaa = -mfbaa; + mfaba = -mfaba; + mfaab = -mfaab; + //////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////////// + //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! see also Eq. (88)-(96) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////////////// + // X - Dir + backwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1, c1); + backwardChimera(mfaba, mfbba, mfcba, vvx, vx2); + backwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3, c1o3); + backwardChimera(mfaab, mfbab, mfcab, vvx, vx2); + backwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2); + backwardChimera(mfacb, mfbcb, mfccb, vvx, vx2); + backwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3, c1o3); + backwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2); + backwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9, c1o9); + + //////////////////////////////////////////////////////////////////////////////////// + // Y - Dir + backwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6, c1o6); + backwardChimera(mfaab, mfabb, mfacb, vvy, vy2); + backwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18, c1o18); + backwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3); + backwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2); + backwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9); + backwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6, c1o6); + backwardChimera(mfcab, mfcbb, mfccb, vvy, vy2); + backwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18, c1o18); + + //////////////////////////////////////////////////////////////////////////////////// + // Z - Dir + backwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9); + backwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36, c1o36); + //////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + //proof correctness + ////////////////////////////////////////////////////////////////////////// +#ifdef PROOF_CORRECTNESS + LBMReal drho_post = (mfaaa + mfaac + mfaca + mfcaa + mfacc + mfcac + mfccc + mfcca) + + (mfaab + mfacb + mfcab + mfccb) + (mfaba + mfabc + mfcba + mfcbc) + (mfbaa + mfbac + mfbca + mfbcc) + + (mfabb + mfcbb) + (mfbab + mfbcb) + (mfbba + mfbbc) + mfbbb; + LBMReal dif = drho - drho_post; +#ifdef SINGLEPRECISION + if (dif > 10.0E-7 || dif < -10.0E-7) +#else + if (dif > 10.0E-15 || dif < -10.0E-15) +#endif + { + UB_THROW(UbException(UB_EXARGS, "rho=" + UbSystem::toString(drho) + ", rho_post=" + UbSystem::toString(drho_post) + + " dif=" + UbSystem::toString(dif) + + " rho is not correct for node " + UbSystem::toString(x1) + "," + UbSystem::toString(x2) + "," + UbSystem::toString(x3) + + " in " + block.lock()->toString() + " step = " + UbSystem::toString(step))); + } +#endif + //////////////////////////////////////////////////////////////////////////////////// + //! - Write distributions: style of reading and writing the distributions from/to stored arrays dependent on timestep is based on the esoteric twist algorithm + //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a> + //! + (*this->localDistributions)(D3Q27System::ET_E, x1, x2, x3) = mfabb; + (*this->localDistributions)(D3Q27System::ET_N, x1, x2, x3) = mfbab; + (*this->localDistributions)(D3Q27System::ET_T, x1, x2, x3) = mfbba; + (*this->localDistributions)(D3Q27System::ET_NE, x1, x2, x3) = mfaab; + (*this->localDistributions)(D3Q27System::ET_NW, x1p, x2, x3) = mfcab; + (*this->localDistributions)(D3Q27System::ET_TE, x1, x2, x3) = mfaba; + (*this->localDistributions)(D3Q27System::ET_TW, x1p, x2, x3) = mfcba; + (*this->localDistributions)(D3Q27System::ET_TN, x1, x2, x3) = mfbaa; + (*this->localDistributions)(D3Q27System::ET_TS, x1, x2p, x3) = mfbca; + (*this->localDistributions)(D3Q27System::ET_TNE, x1, x2, x3) = mfaaa; + (*this->localDistributions)(D3Q27System::ET_TNW, x1p, x2, x3) = mfcaa; + (*this->localDistributions)(D3Q27System::ET_TSE, x1, x2p, x3) = mfaca; + (*this->localDistributions)(D3Q27System::ET_TSW, x1p, x2p, x3) = mfcca; + + (*this->nonLocalDistributions)(D3Q27System::ET_W, x1p, x2, x3) = mfcbb; + (*this->nonLocalDistributions)(D3Q27System::ET_S, x1, x2p, x3) = mfbcb; + (*this->nonLocalDistributions)(D3Q27System::ET_B, x1, x2, x3p) = mfbbc; + (*this->nonLocalDistributions)(D3Q27System::ET_SW, x1p, x2p, x3) = mfccb; + (*this->nonLocalDistributions)(D3Q27System::ET_SE, x1, x2p, x3) = mfacb; + (*this->nonLocalDistributions)(D3Q27System::ET_BW, x1p, x2, x3p) = mfcbc; + (*this->nonLocalDistributions)(D3Q27System::ET_BE, x1, x2, x3p) = mfabc; + (*this->nonLocalDistributions)(D3Q27System::ET_BS, x1, x2p, x3p) = mfbcc; + (*this->nonLocalDistributions)(D3Q27System::ET_BN, x1, x2, x3p) = mfbac; + (*this->nonLocalDistributions)(D3Q27System::ET_BSW, x1p, x2p, x3p) = mfccc; + (*this->nonLocalDistributions)(D3Q27System::ET_BSE, x1, x2p, x3p) = mfacc; + (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1p, x2, x3p) = mfcac; + (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3p) = mfaac; + + (*this->restDistributions)(x1, x2, x3) = mfbbb; + ////////////////////////////////////////////////////////////////////////// + + } + } + } + } +} +////////////////////////////////////////////////////////////////////////// + diff --git a/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h b/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h new file mode 100644 index 0000000000000000000000000000000000000000..47b9a550a3f1b4424322cce5e28c6917945ed8d4 --- /dev/null +++ b/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h @@ -0,0 +1,146 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CumulantK17LBMKernel.h +//! \ingroup LBM +//! \author Konstantin Kutscher, Martin Geier +//======================================================================================= + +#ifndef CumulantK17LBMKernel_h__ +#define CumulantK17LBMKernel_h__ + +#include "LBMKernel.h" +#include "BCProcessor.h" +#include "D3Q27System.h" +#include "basics/utilities/UbTiming.h" +#include "basics/container/CbArray4D.h" +#include "basics/container/CbArray3D.h" + +//! \brief Compressible cumulant LBM kernel. +//! \details LBM implementation that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model +//! +//! The model is publisched in +//! <a href="http://dx.doi.org/10.1016/j.jcp.2017.05.040"><b>[ Geier et al., (2017), 10.1016/j.jcp.2017.05.040]</b></a>, +//! <a href="http://dx.doi.org/10.1016/j.jcp.2017.07.004"><b>[ Geier et al., (2017), 10.1016/j.jcp.2017.07.004]</b></a> +//! +class CumulantK17LBMKernel : public LBMKernel +{ +public: + CumulantK17LBMKernel(); + virtual ~CumulantK17LBMKernel(void); + virtual void calculate(int step); + virtual SPtr<LBMKernel> clone(); + +protected: + inline void forwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K); + inline void backwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K); + inline void forwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2); + inline void backwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2); + + virtual void initDataSet(); + LBMReal f[D3Q27System::ENDF + 1]; + + CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr localDistributions; + CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions; + CbArray3D<LBMReal, IndexerX3X2X1>::CbArray3DPtr restDistributions; + + mu::value_type muX1, muX2, muX3; + mu::value_type muDeltaT; + mu::value_type muNu; + LBMReal forcingX1; + LBMReal forcingX2; + LBMReal forcingX3; +}; + +//////////////////////////////////////////////////////////////////////////////// +//! \brief forward chimera transformation \ref forwardInverseChimeraWithK +//! Transformation from distributions to central moments according to Eq. (6)-(14) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void CumulantK17LBMKernel::forwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K) +{ + using namespace UbMath; + LBMReal m2 = mfa + mfc; + LBMReal m1 = mfc - mfa; + LBMReal m0 = m2 + mfb; + mfa = m0; + m0 *= Kinverse; + m0 += c1; + mfb = (m1 * Kinverse - m0 * vv) * K; + mfc = ((m2 - c2 * m1 * vv) * Kinverse + v2 * m0) * K; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief backward chimera transformation \ref backwardInverseChimeraWithK +//! Transformation from central moments to distributions according to Eq. (57)-(65) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void CumulantK17LBMKernel::backwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K) +{ + using namespace UbMath; + LBMReal m0 = (((mfc - mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (v2 - vv) * c1o2) * K; + LBMReal m1 = (((mfa - mfc) - c2 * mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (-v2)) * K; + mfc = (((mfc + mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (v2 + vv) * c1o2) * K; + mfa = m0; + mfb = m1; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief forward chimera transformation \ref forwardChimera +//! Transformation from distributions to central moments according to Eq. (6)-(14) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations. +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void CumulantK17LBMKernel::forwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2) +{ + using namespace UbMath; + LBMReal m1 = (mfa + mfc) + mfb; + LBMReal m2 = mfc - mfa; + mfc = (mfc + mfa) + (v2 * m1 - c2 * vv * m2); + mfb = m2 - vv * m1; + mfa = m1; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief backward chimera transformation \ref backwardChimera +//! Transformation from central moments to distributions according to Eq. (57)-(65) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations. +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void CumulantK17LBMKernel::backwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2) +{ + using namespace UbMath; + LBMReal ma = (mfc + mfa * (v2 - vv)) * c1o2 + mfb * (vv - c1o2); + LBMReal mb = ((mfa - mfc) - mfa * v2) - c2 * mfb * vv; + mfc = (mfc + mfa * (v2 + vv)) * c1o2 + mfb * (vv + c1o2); + mfb = mb; + mfa = ma; +} + +#endif // CumulantK17LBMKernel_h__ \ No newline at end of file diff --git a/VirtualFluidsCore/LBM/D3Q27System.cpp b/VirtualFluidsCore/LBM/D3Q27System.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e618055721c5b7940fcb75a37717d05c40327179 --- /dev/null +++ b/VirtualFluidsCore/LBM/D3Q27System.cpp @@ -0,0 +1,196 @@ +#include "D3Q27System.h" +namespace D3Q27System +{ + using namespace UbMath; + //index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18//falsch + //f: REST, E, W, N, S, T, B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW + //const int EX1[] = { 0, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1 }; + //const int EX2[] = { 0, 0, 0, 1, -1, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1 }; + //const int EX3[] = { 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1 }; + + //index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + //f: E, W, N, S, T, B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW + const int DX1[] = { 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1 }; + const int DX2[] = { 0, 0, 1, -1, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1 }; + const int DX3[] = { 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1 }; + + ////index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + ////f: E, W, N, S, T, B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW + const double WEIGTH[] = { c2o27, c2o27, c2o27, c2o27, c2o27, c2o27, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216 , c8o27 }; + + + const int INVDIR[] = { + INV_E, + INV_W, + INV_N, + INV_S, + INV_T, + INV_B, + INV_NE, + INV_SW, + INV_SE, + INV_NW, + INV_TE, + INV_BW, + INV_BE, + INV_TW, + INV_TN, + INV_BS, + INV_BN, + INV_TS, + INV_TNE, + INV_TNW, + INV_TSE, + INV_TSW, + INV_BNE, + INV_BNW, + INV_BSE, + INV_BSW }; + + + // The x,y,z component for each normalized direction + const double cNorm[3][ENDDIR] = { + { + double(DX1[0]), double(DX1[1]), + double(DX1[2]), double(DX1[3]), + double(DX1[4]), double(DX1[5]), + double(DX1[6]) / std::sqrt(double(2)), double(DX1[7]) / std::sqrt(double(2)), + double(DX1[8]) / std::sqrt(double(2)), double(DX1[9]) / std::sqrt(double(2)), + double(DX1[10]) / std::sqrt(double(2)), double(DX1[11]) / std::sqrt(double(2)), + double(DX1[12]) / std::sqrt(double(2)), double(DX1[13]) / std::sqrt(double(2)), + double(DX1[14]), double(DX1[15]), + double(DX1[16]), double(DX1[17]), + double(DX1[18]) / std::sqrt(double(3)), double(DX1[19]) / std::sqrt(double(3)), + double(DX1[20]) / std::sqrt(double(3)), double(DX1[21]) / std::sqrt(double(3)), + double(DX1[22]) / std::sqrt(double(3)), double(DX1[23]) / std::sqrt(double(3)), + double(DX1[24]) / std::sqrt(double(3)), double(DX1[25]) / std::sqrt(double(3)) + },{ + double(DX2[0]), double(DX2[1]), + double(DX2[2]), double(DX2[3]), + double(DX2[4]), double(DX2[5]), + double(DX2[6]) / std::sqrt(double(2)), double(DX2[7]) / std::sqrt(double(2)), + double(DX2[8]) / std::sqrt(double(2)), double(DX2[9]) / std::sqrt(double(2)), + double(DX2[10]), double(DX2[11]), + double(DX2[12]), double(DX2[13]), + double(DX2[14]) / std::sqrt(double(2)), double(DX2[15]) / std::sqrt(double(2)), + double(DX2[16]) / std::sqrt(double(2)), double(DX2[17]) / std::sqrt(double(2)), + double(DX2[18]) / std::sqrt(double(3)), double(DX2[19]) / std::sqrt(double(3)), + double(DX2[20]) / std::sqrt(double(3)), double(DX2[21]) / std::sqrt(double(3)), + double(DX2[22]) / std::sqrt(double(3)), double(DX2[23]) / std::sqrt(double(3)), + double(DX2[24]) / std::sqrt(double(3)), double(DX2[25]) / std::sqrt(double(3)) + },{ + double(DX3[0]), double(DX3[1]), + double(DX3[2]), double(DX3[3]), + double(DX3[4]), double(DX3[5]), + double(DX3[6]), double(DX3[7]), + double(DX3[8]), double(DX3[9]), + double(DX3[10]) / std::sqrt(double(2)), double(DX3[11]) / std::sqrt(double(2)), + double(DX3[12]) / std::sqrt(double(2)), double(DX3[13]) / std::sqrt(double(2)), + double(DX3[14]) / std::sqrt(double(2)), double(DX3[15]) / std::sqrt(double(2)), + double(DX3[16]) / std::sqrt(double(2)), double(DX3[17]) / std::sqrt(double(2)), + double(DX3[18]) / std::sqrt(double(3)), double(DX3[19]) / std::sqrt(double(3)), + double(DX3[20]) / std::sqrt(double(3)), double(DX3[21]) / std::sqrt(double(3)), + double(DX3[22]) / std::sqrt(double(3)), double(DX3[23]) / std::sqrt(double(3)), + double(DX3[24]) / std::sqrt(double(3)), double(DX3[25]) / std::sqrt(double(3)) + } + }; + +} + +//const int FSTARTDIR = 0; +//const int FENDDIR = 25; //D3Q27 + +//const int STARTF = 0; +//const int ENDF = 26; //D3Q27 + +//const int EX1[ENDF+1]; +//const int EX2[ENDF+1]; +//const int EX3[ENDF+1]; + +//const int STARTDIR = 0; +//const int ENDDIR = 26; //alle geometrischen richtungen + +//const int DX1[ENDDIR+1]; +//const int DX2[ENDDIR+1]; +//const int DX3[ENDDIR+1]; + + +//const int E /*f1 */ = 0; +//const int W /*f2 */ = 1; +//const int N /*f3 */ = 2; +//const int S /*f4 */ = 3; +//const int T /*f5 */ = 4; +//const int B /*f6 */ = 5; +//const int NE /*f7 */ = 6; +//const int SW /*f8 */ = 7; +//const int SE /*f9 */ = 8; +//const int NW /*f10*/ = 9; +//const int TE /*f11*/ = 10; +//const int BW /*f12*/ = 11; +//const int BE /*f13*/ = 12; +//const int TW /*f14*/ = 13; +//const int TN /*f15*/ = 14; +//const int BS /*f16*/ = 15; +//const int BN /*f17*/ = 16; +//const int TS /*f18*/ = 17; +//const int TNE = 18; +//const int TNW = 19; +//const int TSE = 20; +//const int TSW = 21; +//const int BNE = 22; +//const int BNW = 23; +//const int BSE = 24; +//const int BSW = 25; +//const int REST /*f0 */ = 26; + +//const int INV_E = W; +//const int INV_W = E; +//const int INV_N = S; +//const int INV_S = N; +//const int INV_T = B; +//const int INV_B = T; +//const int INV_NE = SW; +//const int INV_SW = NE; +//const int INV_SE = NW; +//const int INV_NW = SE; +//const int INV_TE = BW; +//const int INV_BW = TE; +//const int INV_BE = TW; +//const int INV_TW = BE; +//const int INV_TN = BS; +//const int INV_BS = TN; +//const int INV_BN = TS; +//const int INV_TS = BN; +//const int INV_TNE = BSW; +//const int INV_TNW = BSE; +//const int INV_TSE = BNW; +//const int INV_TSW = BNE; +//const int INV_BNE = TSW; +//const int INV_BNW = TSE; +//const int INV_BSE = TNW; +//const int INV_BSW = TNE; + +//const int INVDIR[ENDDIR+1]; + +//const int M_RHO = 0; +//const int M_EN = 1; +//const int M_EPS = 2; +//const int M_JX1 = 3; +//const int M_QX1 = 4; +//const int M_JX2 = 5; +//const int M_QX2 = 6; +//const int M_JX3 = 7; +//const int M_QX3 = 8; +//const int M_3PX1X1 = 9; +//const int M_3PIX1X1 = 10; +//const int M_PWW = 11; +//const int M_PIWW = 12; +//const int M_PX1X2 = 13; +//const int M_PX2X3 = 14; +//const int M_PX1X3 = 15; +//const int M_MX1 = 16; +//const int M_MX2 = 17; +//const int M_MX3 = 18; + +//const int STARTM = 0; +//const int ENDM = 18; //D3Q27 diff --git a/VirtualFluidsCore/LBM/D3Q27System.h b/VirtualFluidsCore/LBM/D3Q27System.h new file mode 100644 index 0000000000000000000000000000000000000000..9e1426a06eb14bd59f8b4d9fe86e4df63ecb16a4 --- /dev/null +++ b/VirtualFluidsCore/LBM/D3Q27System.h @@ -0,0 +1,594 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file D3Q27System.h +//! \ingroup LBM +//! \author Konstantin Kutscher, Sebastian Geller, Sören Freudiger +//======================================================================================= + +#ifndef D3Q27SYSTEM_H +#define D3Q27SYSTEM_H + +#include <cmath> +#include <string> +#include <iostream> + +#include "UbException.h" +#include "UbMath.h" +#include "LBMSystem.h" + +//! \brief namespace for global system-functions +namespace D3Q27System +{ + ////////////////////////////////////////////////////////////////////////// + //DIRECTION STUFF + static const int FSTARTDIR = 0; + static const int FENDDIR = 25; //D3Q27 + + static const int STARTF = 0; + static const int ENDF = 26; //D3Q27 + + static const int STARTDIR = 0; + static const int ENDDIR = 26; //all geometric directions + + extern const int DX1[ENDDIR+1]; + extern const int DX2[ENDDIR+1]; + extern const int DX3[ENDDIR+1]; + extern const double WEIGTH[ENDDIR+1]; + + extern const double cNorm[3][ENDDIR]; + + static const int E = 0; + static const int W = 1; + static const int N = 2; + static const int S = 3; + static const int T = 4; + static const int B = 5; + static const int NE = 6; + static const int SW = 7; + static const int SE = 8; + static const int NW = 9; + static const int TE = 10; + static const int BW = 11; + static const int BE = 12; + static const int TW = 13; + static const int TN = 14; + static const int BS = 15; + static const int BN = 16; + static const int TS = 17; + static const int TNE = 18; + static const int TNW = 19; + static const int TSE = 20; + static const int TSW = 21; + static const int BNE = 22; + static const int BNW = 23; + static const int BSE = 24; + static const int BSW = 25; + static const int REST = 26; + + static const int INV_E = W; + static const int INV_W = E; + static const int INV_N = S; + static const int INV_S = N; + static const int INV_T = B; + static const int INV_B = T; + static const int INV_NE = SW; + static const int INV_SW = NE; + static const int INV_SE = NW; + static const int INV_NW = SE; + static const int INV_TE = BW; + static const int INV_BW = TE; + static const int INV_BE = TW; + static const int INV_TW = BE; + static const int INV_TN = BS; + static const int INV_BS = TN; + static const int INV_BN = TS; + static const int INV_TS = BN; + static const int INV_TNE = BSW; + static const int INV_TNW = BSE; + static const int INV_TSE = BNW; + static const int INV_TSW = BNE; + static const int INV_BNE = TSW; + static const int INV_BNW = TSE; + static const int INV_BSE = TNW; + static const int INV_BSW = TNE; + + extern const int INVDIR[ENDDIR+1]; + + static const int ET_E = 0; + static const int ET_W = 0; + static const int ET_N = 1; + static const int ET_S = 1; + static const int ET_T = 2; + static const int ET_B = 2; + static const int ET_NE = 3; + static const int ET_SW = 3; + static const int ET_SE = 4; + static const int ET_NW = 4; + static const int ET_TE = 5; + static const int ET_BW = 5; + static const int ET_BE = 6; + static const int ET_TW = 6; + static const int ET_TN = 7; + static const int ET_BS = 7; + static const int ET_BN = 8; + static const int ET_TS = 8; + static const int ET_TNE = 9; + static const int ET_BSW = 9; + static const int ET_TNW = 10; + static const int ET_BSE = 10; + static const int ET_TSE = 11; + static const int ET_BNW = 11; + static const int ET_TSW = 12; + static const int ET_BNE = 12; + + + ////////////////////////////////////////////////////////////////////////// + //MACROSCOPIC VALUES + /*=====================================================================*/ + static LBMReal getDensity(const LBMReal* const& f/*[27]*/) + { + return ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE])) + +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW])) + +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S]) + +(f[T] + f[B]))+f[REST]; + } + /*=====================================================================*/ + //ATTENTION: does not apply to all models -> use certificate instead of static! to do + static LBMReal getPressure(const LBMReal* const& f/*[27]*/) + { + return REAL_CAST( UbMath::c1o3 )*getDensity(f); + } + /*=====================================================================*/ + static LBMReal getIncompVelocityX1(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) + + (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) + + (f[E]-f[W])); + } + /*=====================================================================*/ + static LBMReal getIncompVelocityX2(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) + + (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) + + (f[N]-f[S])); + } + /*=====================================================================*/ + static LBMReal getIncompVelocityX3(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE] - f[BSW]) + (f[TSE] - f[BNW])) + ((f[TNW] - f[BSE]) + (f[TSW] - f[BNE]))) + + (((f[TS] - f[BN]) + (f[TN] - f[BS])) + ((f[TW] - f[BE]) + (f[TE] - f[BW]))) + + (f[T] - f[B])); + } + /*=====================================================================*/ + static void calcDensity(const LBMReal* const& f/*[27]*/, LBMReal& rho) + { + rho = ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE])) + +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW])) + +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S]) + +(f[T] + f[B]))+f[REST]; + + } + /*=====================================================================*/ + static void calcIncompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1) + { + vx1 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) + + (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) + + (f[E]-f[W])); + } + /*=====================================================================*/ + static void calcIncompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2) + { + vx2 = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) + + (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) + + (f[N]-f[S])); + } + /*=====================================================================*/ + static void calcIncompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3) + { + vx3 =((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) + + (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) + + (f[T]-f[B])); + } + /*=====================================================================*/ + static LBMReal getCompVelocityX1(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) + + (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) + + (f[E]-f[W]))/getDensity(f); + } + /*=====================================================================*/ + static LBMReal getCompVelocityX2(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) + + (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) + + (f[N]-f[S]))/getDensity(f); + } + /*=====================================================================*/ + static LBMReal getCompVelocityX3(const LBMReal* const& f/*[27]*/) + { + return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) + + (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) + + (f[T]-f[B]))/getDensity(f); + } + /*=====================================================================*/ + static void calcCompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1) + { + vx1 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) + + (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) + + (f[E]-f[W]))/getDensity(f); + } + /*=====================================================================*/ + static void calcCompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2) + { + vx2 = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) + + (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) + + (f[N]-f[S]))/getDensity(f); + } + /*=====================================================================*/ + static void calcCompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3) + { + vx3 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) + + (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) + + (f[T]-f[B]))/getDensity(f); + } + /*=====================================================================*/ + static void calcIncompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3) + { + D3Q27System::calcDensity(f, rho); + D3Q27System::calcIncompVelocityX1(f, vx1); + D3Q27System::calcIncompVelocityX2(f, vx2); + D3Q27System::calcIncompVelocityX3(f, vx3); + } + + /*=====================================================================*/ + static void calcCompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& drho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3) + { + D3Q27System::calcDensity(f, drho); + D3Q27System::calcIncompVelocityX1(f, vx1); + D3Q27System::calcIncompVelocityX2(f, vx2); + D3Q27System::calcIncompVelocityX3(f, vx3); + LBMReal rho = drho+UbMath::c1; + vx1/=rho; + vx2/=rho; + vx3/=rho; + } + ////////////////////////////////////////////////////////////////////////// + static LBMReal getCompFeqForDirection(const int& direction, const LBMReal& drho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3) + { + using namespace UbMath; + + LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3); + + ////----- + LBMReal rho = drho+c1; + switch (direction) + { + case REST: return REAL_CAST(c8o27*(drho+rho*(-cu_sq))); + case E: return REAL_CAST(c2o27*(drho+rho*(3.0*(vx1)+c9o2*(vx1)*(vx1)-cu_sq))); + case W: return REAL_CAST(c2o27*(drho+rho*(3.0*(-vx1)+c9o2*(-vx1)*(-vx1)-cu_sq))); + case N: return REAL_CAST(c2o27*(drho+rho*(3.0*(vx2)+c9o2*(vx2)*(vx2)-cu_sq))); + case S: return REAL_CAST(c2o27*(drho+rho*(3.0*(-vx2)+c9o2*(-vx2)*(-vx2)-cu_sq))); + case T: return REAL_CAST(c2o27*(drho+rho*(3.0*(vx3)+c9o2*(vx3)*(vx3)-cu_sq))); + case B: return REAL_CAST(c2o27*(drho+rho*(3.0*(-vx3)+c9o2*(-vx3)*(-vx3)-cu_sq))); + case NE: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx1+vx2)+c9o2*(vx1+vx2)*(vx1+vx2)-cu_sq))); + case SW: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq))); + case SE: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx1-vx2)+c9o2*(vx1-vx2)*(vx1-vx2)-cu_sq))); + case NW: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq))); + case TE: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx1+vx3)+c9o2*(vx1+vx3)*(vx1+vx3)-cu_sq))); + case BW: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq))); + case BE: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx1-vx3)+c9o2*(vx1-vx3)*(vx1-vx3)-cu_sq))); + case TW: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq))); + case TN: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx2+vx3)+c9o2*(vx2+vx3)*(vx2+vx3)-cu_sq))); + case BS: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq))); + case BN: return REAL_CAST(c1o54*(drho+rho*(3.0*(vx2-vx3)+c9o2*(vx2-vx3)*(vx2-vx3)-cu_sq))); + case TS: return REAL_CAST(c1o54*(drho+rho*(3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq))); + case TNE: return REAL_CAST(c1o216*(drho+rho*(3.0*(vx1+vx2+vx3)+c9o2*(vx1+vx2+vx3)*(vx1+vx2+vx3)-cu_sq))); + case BSW: return REAL_CAST(c1o216*(drho+rho*(3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq))); + case BNE: return REAL_CAST(c1o216*(drho+rho*(3.0*(vx1+vx2-vx3)+c9o2*(vx1+vx2-vx3)*(vx1+vx2-vx3)-cu_sq))); + case TSW: return REAL_CAST(c1o216*(drho+rho*(3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq))); + case TSE: return REAL_CAST(c1o216*(drho+rho*(3.0*(vx1-vx2+vx3)+c9o2*(vx1-vx2+vx3)*(vx1-vx2+vx3)-cu_sq))); + case BNW: return REAL_CAST(c1o216*(drho+rho*(3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq))); + case BSE: return REAL_CAST(c1o216*(drho+rho*(3.0*(vx1-vx2-vx3)+c9o2*(vx1-vx2-vx3)*(vx1-vx2-vx3)-cu_sq))); + case TNW: return REAL_CAST(c1o216*(drho+rho*(3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq))); + default: throw UbException(UB_EXARGS, "unknown dir"); + } + + } + ////////////////////////////////////////////////////////////////////////// + static void calcCompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& drho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3) + { + using namespace UbMath; + + LBMReal cu_sq = 1.5*(vx1*vx1+vx2*vx2+vx3*vx3); + LBMReal rho = drho+c1; + + feq[REST] = c8o27*(drho+rho*(-cu_sq)); + feq[E] = c2o27*(drho+rho*(3.0*(vx1)+c9o2*(vx1)*(vx1)-cu_sq)); + feq[W] = c2o27*(drho+rho*(3.0*(-vx1)+c9o2*(-vx1)*(-vx1)-cu_sq)); + feq[N] = c2o27*(drho+rho*(3.0*(vx2)+c9o2*(vx2)*(vx2)-cu_sq)); + feq[S] = c2o27*(drho+rho*(3.0*(-vx2)+c9o2*(-vx2)*(-vx2)-cu_sq)); + feq[T] = c2o27*(drho+rho*(3.0*(vx3)+c9o2*(vx3)*(vx3)-cu_sq)); + feq[B] = c2o27*(drho+rho*(3.0*(-vx3)+c9o2*(-vx3)*(-vx3)-cu_sq)); + feq[NE] = c1o54*(drho+rho*(3.0*(vx1+vx2)+c9o2*(vx1+vx2)*(vx1+vx2)-cu_sq)); + feq[SW] = c1o54*(drho+rho*(3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq)); + feq[SE] = c1o54*(drho+rho*(3.0*(vx1-vx2)+c9o2*(vx1-vx2)*(vx1-vx2)-cu_sq)); + feq[NW] = c1o54*(drho+rho*(3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq)); + feq[TE] = c1o54*(drho+rho*(3.0*(vx1+vx3)+c9o2*(vx1+vx3)*(vx1+vx3)-cu_sq)); + feq[BW] = c1o54*(drho+rho*(3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq)); + feq[BE] = c1o54*(drho+rho*(3.0*(vx1-vx3)+c9o2*(vx1-vx3)*(vx1-vx3)-cu_sq)); + feq[TW] = c1o54*(drho+rho*(3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq)); + feq[TN] = c1o54*(drho+rho*(3.0*(vx2+vx3)+c9o2*(vx2+vx3)*(vx2+vx3)-cu_sq)); + feq[BS] = c1o54*(drho+rho*(3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq)); + feq[BN] = c1o54*(drho+rho*(3.0*(vx2-vx3)+c9o2*(vx2-vx3)*(vx2-vx3)-cu_sq)); + feq[TS] = c1o54*(drho+rho*(3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq)); + feq[TNE] = c1o216*(drho+rho*(3.0*(vx1+vx2+vx3)+c9o2*(vx1+vx2+vx3)*(vx1+vx2+vx3)-cu_sq)); + feq[BSW] = c1o216*(drho+rho*(3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq)); + feq[BNE] = c1o216*(drho+rho*(3.0*(vx1+vx2-vx3)+c9o2*(vx1+vx2-vx3)*(vx1+vx2-vx3)-cu_sq)); + feq[TSW] = c1o216*(drho+rho*(3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq)); + feq[TSE] = c1o216*(drho+rho*(3.0*(vx1-vx2+vx3)+c9o2*(vx1-vx2+vx3)*(vx1-vx2+vx3)-cu_sq)); + feq[BNW] = c1o216*(drho+rho*(3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq)); + feq[BSE] = c1o216*(drho+rho*(3.0*(vx1-vx2-vx3)+c9o2*(vx1-vx2-vx3)*(vx1-vx2-vx3)-cu_sq)); + feq[TNW] = c1o216*(drho+rho*(3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq)); + } + ////////////////////////////////////////////////////////////////////////// + static LBMReal getIncompFeqForDirection(const int& direction,const LBMReal& drho, const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3) + { + using namespace UbMath; + + LBMReal cu_sq=1.5f*(vx1*vx1+vx2*vx2+vx3*vx3); + + switch(direction) + { + case REST : return REAL_CAST( c8o27*(drho-cu_sq)); + case E : return REAL_CAST( c2o27*(drho+3.0*( vx1 )+c9o2*( vx1 )*( vx1 )-cu_sq)); + case W : return REAL_CAST( c2o27*(drho+3.0*(-vx1 )+c9o2*(-vx1 )*(-vx1 )-cu_sq)); + case N : return REAL_CAST( c2o27*(drho+3.0*( vx2)+c9o2*( vx2)*( vx2)-cu_sq)); + case S : return REAL_CAST( c2o27*(drho+3.0*( -vx2)+c9o2*( -vx2)*( -vx2)-cu_sq)); + case T : return REAL_CAST( c2o27*(drho+3.0*( vx3 )+c9o2*( vx3)*( vx3)-cu_sq)); + case B : return REAL_CAST( c2o27*(drho+3.0*( -vx3)+c9o2*( -vx3)*( -vx3)-cu_sq)); + case NE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq)); + case SW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq)); + case SE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq)); + case NW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq)); + case TE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq)); + case BW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq)); + case BE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq)); + case TW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq)); + case TN : return REAL_CAST( c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq)); + case BS : return REAL_CAST( c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq)); + case BN : return REAL_CAST( c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq)); + case TS : return REAL_CAST( c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq)); + case TNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq)); + case BSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq)); + case BNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq)); + case TSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq)); + case TSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq)); + case BNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq)); + case BSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq)); + case TNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq)); + default: throw UbException(UB_EXARGS,"unknown dir"); + } + } + ////////////////////////////////////////////////////////////////////////// + static void calcIncompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& drho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3) + { + using namespace UbMath; + + LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3); + + feq[REST] = c8o27*(drho-cu_sq); + feq[E] = c2o27*(drho+3.0*( vx1 )+c9o2*( vx1 )*( vx1 )-cu_sq); + feq[W] = c2o27*(drho+3.0*(-vx1 )+c9o2*(-vx1 )*(-vx1 )-cu_sq); + feq[N] = c2o27*(drho+3.0*( vx2)+c9o2*( vx2)*( vx2)-cu_sq); + feq[S] = c2o27*(drho+3.0*( -vx2)+c9o2*( -vx2)*( -vx2)-cu_sq); + feq[T] = c2o27*(drho+3.0*( vx3 )+c9o2*( vx3)*( vx3)-cu_sq); + feq[B] = c2o27*(drho+3.0*( -vx3)+c9o2*( -vx3)*( -vx3)-cu_sq); + feq[NE] = c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq); + feq[SW] = c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq); + feq[SE] = c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq); + feq[NW] = c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq); + feq[TE] = c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq); + feq[BW] = c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq); + feq[BE] = c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq); + feq[TW] = c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq); + feq[TN] = c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq); + feq[BS] = c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq); + feq[BN] = c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq); + feq[TS] = c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq); + feq[TNE] = c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq); + feq[BSW] = c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq); + feq[BNE] = c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq); + feq[TSW] = c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq); + feq[TSE] = c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq); + feq[BNW] = c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq); + feq[BSE] = c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq); + feq[TNW] = c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq); + } + ////////////////////////////////////////////////////////////////////////// + static inline float getBoundaryVelocityForDirection(const int& direction, const float& bcVelocityX1,const float& bcVelocityX2,const float& bcVelocityX3) + { + using namespace UbMath; + + switch(direction) + { + case E: return (float)( UbMath::c4o9*(+bcVelocityX1) ); + case W: return (float)( UbMath::c4o9*(-bcVelocityX1) ); + case N: return (float)( UbMath::c4o9*(+bcVelocityX2) ); + case S: return (float)( UbMath::c4o9*(-bcVelocityX2) ); + case T: return (float)( UbMath::c4o9*(+bcVelocityX3) ); + case B: return (float)( UbMath::c4o9*(-bcVelocityX3) ); + case NE: return (float)( UbMath::c1o9*(+bcVelocityX1+bcVelocityX2 ) ); + case SW: return (float)( UbMath::c1o9*(-bcVelocityX1-bcVelocityX2 ) ); + case SE: return (float)( UbMath::c1o9*(+bcVelocityX1-bcVelocityX2 ) ); + case NW: return (float)( UbMath::c1o9*(-bcVelocityX1+bcVelocityX2 ) ); + case TE: return (float)( UbMath::c1o9*(+bcVelocityX1 +bcVelocityX3) ); + case BW: return (float)( UbMath::c1o9*(-bcVelocityX1 -bcVelocityX3) ); + case BE: return (float)( UbMath::c1o9*(+bcVelocityX1 -bcVelocityX3) ); + case TW: return (float)( UbMath::c1o9*(-bcVelocityX1 +bcVelocityX3) ); + case TN: return (float)( UbMath::c1o9*( +bcVelocityX2+bcVelocityX3) ); + case BS: return (float)( UbMath::c1o9*( -bcVelocityX2-bcVelocityX3) ); + case BN: return (float)( UbMath::c1o9*( +bcVelocityX2-bcVelocityX3) ); + case TS: return (float)( UbMath::c1o9*( -bcVelocityX2+bcVelocityX3) ); + case TNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2+bcVelocityX3) ); + case BSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2-bcVelocityX3) ); + case BNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2-bcVelocityX3) ); + case TSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2+bcVelocityX3) ); + case TSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2+bcVelocityX3) ); + case BNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2-bcVelocityX3) ); + case BSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2-bcVelocityX3) ); + case TNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2+bcVelocityX3) ); + default: throw UbException(UB_EXARGS,"unknown direction"); + } + } + /*=====================================================================*/ + static const int& getInvertDirection(const int& direction) + { + #ifdef _DEBUG + if(direction<STARTDIR || direction>ENDDIR) + throw UbException(UB_EXARGS,"unknown direction"); + #endif + return INVDIR[direction]; + } + /*=====================================================================*/ + static void getLBMDirections(std::vector<int>& dirs, bool onlyLBdirs = false) + { + std::vector<int> D3Q27Dirs; + if(onlyLBdirs) /*FSTARTDIR->FENDDIR*/ + { + dirs.resize(FENDDIR+1); + for(int dir=FSTARTDIR; dir<=FENDDIR; ++dir) + dirs[dir] = dir; + } + else /*STARTDIR->ENDDIR*/ + { + dirs.resize(ENDDIR+1); + for(int dir=STARTDIR; dir<=ENDDIR; ++dir) + dirs[dir] = dir; + } + } +////////////////////////////////////////////////////////////////////////// + static std::vector<int> getEX(const int& exn) + { + std::vector<int> ex; + ex.resize(ENDDIR+1); + switch (exn) + { + case 1: + for(int dir=STARTDIR; dir<ENDDIR; ++dir) + ex[dir] = DX1[dir]; + break; + case 2: + for(int dir=STARTDIR; dir<ENDDIR; ++dir) + ex[dir] = DX2[dir]; + break; + case 3: + for(int dir=STARTDIR; dir<ENDDIR; ++dir) + ex[dir] = DX3[dir]; + break; + } + return ex; + } +////////////////////////////////////////////////////////////////////////// + static inline void calcDistanceToNeighbors(std::vector<double>& distNeigh, const double& deltaX1) + { + //distNeigh.resize(FENDDIR+1, UbMath::sqrt2*deltaX1); + double sqrt3 = UbMath::sqrt3; + double sqrt2 = UbMath::sqrt2; + distNeigh[E] = distNeigh[W] = distNeigh[N] = deltaX1; + distNeigh[S] = distNeigh[T] = distNeigh[B] = deltaX1; + distNeigh[NE] = distNeigh[NW] = distNeigh[SW] = distNeigh[SE] = sqrt2*deltaX1; + distNeigh[TE] = distNeigh[TN] = distNeigh[TW] = distNeigh[TS] = sqrt2*deltaX1; + distNeigh[BE] = distNeigh[BN] = distNeigh[BW] = distNeigh[BS] = sqrt2*deltaX1; + distNeigh[TNE] = distNeigh[TNW] = distNeigh[TSE] = distNeigh[TSW] = sqrt3*deltaX1; + distNeigh[BNE] = distNeigh[BNW] = distNeigh[BSE] = distNeigh[BSW] = sqrt3*deltaX1; + } +////////////////////////////////////////////////////////////////////////// + static inline void calcDistanceToNeighbors(std::vector<double>& distNeigh, const double& deltaX1,const double& deltaX2,const double& deltaX3) + { + //distNeigh.resize(FENDDIR+1, UbMath::sqrt2*deltaX1); + double sqrt3 = UbMath::sqrt3; + double sqrt2 = UbMath::sqrt2; + distNeigh[E] = distNeigh[W] = deltaX1; + distNeigh[N] = distNeigh[S] = deltaX2; + distNeigh[T] = distNeigh[B] = deltaX3; + distNeigh[NE] = distNeigh[NW] = distNeigh[SW] = distNeigh[SE] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2); + distNeigh[TE] = distNeigh[TN] = distNeigh[TW] = distNeigh[TS] = sqrt(deltaX1*deltaX1+deltaX3*deltaX3); + distNeigh[BE] = distNeigh[BN] = distNeigh[BW] = distNeigh[BS] = sqrt(deltaX2*deltaX2+deltaX3*deltaX3); + distNeigh[TNE] = distNeigh[TNW] = distNeigh[TSE] = distNeigh[TSW] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3); + distNeigh[BNE] = distNeigh[BNW] = distNeigh[BSE] = distNeigh[BSW] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3); + } +////////////////////////////////////////////////////////////////////////// + static inline void initRayVectors(double* const& rayX1, double* const& rayX2, double* const& rayX3) + { + using namespace UbMath; + + int fdir; + double c1oS2 = UbMath::one_over_sqrt2; + double c1oS3 = UbMath::one_over_sqrt3; + fdir = E; rayX1[fdir] = 1.0; rayX2[fdir] = 0.0; rayX3[fdir] = 0.0; + fdir = W; rayX1[fdir] = -1.0; rayX2[fdir] = 0.0; rayX3[fdir] = 0.0; + fdir = N; rayX1[fdir] = 0.0; rayX2[fdir] = 1.0; rayX3[fdir] = 0.0; + fdir = S; rayX1[fdir] = 0.0; rayX2[fdir] = -1.0; rayX3[fdir] = 0.0; + fdir = T; rayX1[fdir] = 0.0; rayX2[fdir] = 0.0; rayX3[fdir] = 1.0; + fdir = B; rayX1[fdir] = 0.0; rayX2[fdir] = 0.0; rayX3[fdir] = -1.0; + fdir = NE; rayX1[fdir] = c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] = 0.0; + fdir = SW; rayX1[fdir] = -c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] = 0.0; + fdir = SE; rayX1[fdir] = c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] = 0.0; + fdir = NW; rayX1[fdir] = -c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] = 0.0; + fdir = TE; rayX1[fdir] = c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = c1oS2; + fdir = BW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = -c1oS2; + fdir = BE; rayX1[fdir] = c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = -c1oS2; + fdir = TW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0; rayX3[fdir] = c1oS2; + fdir = TN; rayX1[fdir] = 0.0; rayX2[fdir] = c1oS2; rayX3[fdir] = c1oS2; + fdir = BS; rayX1[fdir] = 0.0; rayX2[fdir] =-c1oS2; rayX3[fdir] = -c1oS2; + fdir = BN; rayX1[fdir] = 0.0; rayX2[fdir] = c1oS2; rayX3[fdir] = -c1oS2; + fdir = TS; rayX1[fdir] = 0.0; rayX2[fdir] =-c1oS2; rayX3[fdir] = c1oS2; + fdir = TNE; rayX1[fdir] = c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = c1oS3; + fdir = TNW; rayX1[fdir] = -c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = c1oS3; + fdir = TSE; rayX1[fdir] = c1oS3; rayX2[fdir] = -c1oS3; rayX3[fdir] = c1oS3; + fdir = TSW; rayX1[fdir] = -c1oS3; rayX2[fdir] = -c1oS3; rayX3[fdir] = c1oS3; + fdir = BNE; rayX1[fdir] = c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = -c1oS3; + fdir = BNW; rayX1[fdir] = -c1oS3; rayX2[fdir] = c1oS3; rayX3[fdir] = -c1oS3; + fdir = BSE; rayX1[fdir] = c1oS3; rayX2[fdir] = -c1oS3; rayX3[fdir] = -c1oS3; + fdir = BSW; rayX1[fdir] = -c1oS3; rayX2[fdir] = -c1oS3; rayX3[fdir] = -c1oS3; + } +////////////////////////////////////////////////////////////////////////// + static inline LBMReal calcPress(const LBMReal* const f, LBMReal rho, LBMReal vx1, LBMReal vx2, LBMReal vx3) + { + using namespace UbMath; + LBMReal OxxPyyPzz = c1; + return ((f[E]+f[W]+f[N]+f[S]+f[T]+f[B]+c2*(f[NE]+f[SW]+f[SE]+f[NW]+f[TE]+f[BW]+f[BE]+f[TW]+f[TN]+f[BS]+f[BN]+f[TS])+ + c3*(f[TNE]+f[TSW]+f[TSE]+f[TNW]+f[BNE]+f[BSW]+f[BSE]+f[BNW])-(vx1*vx1+vx2*vx2+vx3*vx3))*(c1-c1o2*OxxPyyPzz)+OxxPyyPzz*c1o2*(rho))*c1o3; + } +} + +#endif + + + diff --git a/VirtualFluidsCore/LBM/ILBMKernel.h b/VirtualFluidsCore/LBM/ILBMKernel.h new file mode 100644 index 0000000000000000000000000000000000000000..526bdd2fe828e1280b6996bc7cba9bdd1be21e20 --- /dev/null +++ b/VirtualFluidsCore/LBM/ILBMKernel.h @@ -0,0 +1,63 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file ILBMKernel.h +//! \ingroup LBM +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef I_LBMKERNEL_H +#define I_LBMKERNEL_H + +#include <PointerDefinitions.h> + +class BCProcessor; +class DataSet3D; + +//! Abstract class provides interface for LBM kernel +class ILBMKernel +{ +public: + virtual ~ILBMKernel() {}; + + virtual void calculate(int step) = 0; + virtual void swapDistributions() = 0; + + virtual bool getCompressible() const = 0; + virtual SPtr<BCProcessor> getBCProcessor() const = 0; + virtual void setBCProcessor(SPtr<BCProcessor> bcProcessor) = 0; + virtual SPtr<DataSet3D> getDataSet() const = 0; + virtual double getCollisionFactor() const = 0; + virtual void setCollisionFactor(double collFactor) = 0; + virtual bool isInsideOfDomain(const int &x1, const int &x2, const int &x3) const = 0; + virtual int getGhostLayerWidth() const = 0; + virtual double getDeltaT() const = 0; + virtual bool getWithForcing() const = 0; +}; + +#endif diff --git a/VirtualFluidsCore/LBM/LBMKernel.cpp b/VirtualFluidsCore/LBM/LBMKernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dcb20a0533198f39c92e264b7ea3b8475723fe1d --- /dev/null +++ b/VirtualFluidsCore/LBM/LBMKernel.cpp @@ -0,0 +1,261 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LBMKernel.cpp +//! \ingroup LBM +//! \author Konstantin Kutscher +//======================================================================================= + +#include "LBMKernel.h" +#include "DataSet3D.h" +#include "BCProcessor.h" +#include "Block3D.h" +#include "BCArray3D.h" + +LBMKernel::LBMKernel() : ghostLayerWidth(1), + deltaT(1.0), + withForcing(false), + withSpongeLayer(false), + compressible(false) +{ + this->setForcingX1(0.0); + this->setForcingX2(0.0); + this->setForcingX3(0.0); + dataSet = SPtr<DataSet3D>(new DataSet3D()); + this->nx[0] = 0; + this->nx[1] = 0; + this->nx[2] = 0; +} +////////////////////////////////////////////////////////////////////////// +LBMKernel::~LBMKernel() +{ + +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setBCProcessor(SPtr<BCProcessor> bcp) +{ + bcProcessor = bcp; +} +////////////////////////////////////////////////////////////////////////// +SPtr<BCProcessor> LBMKernel::getBCProcessor() const +{ + return bcProcessor; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setCollisionFactor(double collFactor) +{ + this->collFactor = collFactor; +} +////////////////////////////////////////////////////////////////////////// +double LBMKernel::getCollisionFactor() const +{ + return collFactor; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX1(LBMReal forcingX1) +{ + this->muForcingX1.SetExpr( UbSystem::toString(forcingX1,LBMRealLim::digits10) ); + this->checkFunction(muForcingX1); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX2(LBMReal forcingX2) +{ + this->muForcingX2.SetExpr( UbSystem::toString(forcingX2,LBMRealLim::digits10) ); + this->checkFunction(muForcingX2); +} +void LBMKernel::setForcingX3(LBMReal forcingX3) +{ + this->muForcingX3.SetExpr( UbSystem::toString(forcingX3,LBMRealLim::digits10) ); + this->checkFunction(muForcingX3); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX1( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muForcingX1 = parser; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX2( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muForcingX2 = parser; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX3( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muForcingX3 = parser; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX1( const std::string& muParserString) +{ + this->muForcingX1.SetExpr(muParserString); + this->checkFunction(muForcingX1); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setForcingX2( const std::string& muParserString) +{ + this->muForcingX2.SetExpr(muParserString); + this->checkFunction(muForcingX2); +} +void LBMKernel::setForcingX3( const std::string& muParserString) +{ + this->muForcingX3.SetExpr(muParserString); + this->checkFunction(muForcingX3); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::checkFunction(mu::Parser fct) +{ + double x1=1.0,x2=1.0,x3=1.0, dt=1.0, nue=1.0; + fct.DefineVar("x1",&x1); + fct.DefineVar("x2",&x2); + fct.DefineVar("x3",&x3); + fct.DefineVar("dt",&dt); + fct.DefineVar("nue",&nue); + + try + { + fct.Eval(); + fct.ClearVar(); + } + catch(mu::ParserError& e) + { + throw UbException(UB_EXARGS,"function: "+e.GetExpr() + (std::string)"error: "+e.GetMsg() + +(std::string)", only x1,x2,x3,dx are allowed as variables" ); + } +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setGhostLayerWidth(int witdh) +{ + ghostLayerWidth = witdh; +} +////////////////////////////////////////////////////////////////////////// +int LBMKernel::getGhostLayerWidth() const +{ + return ghostLayerWidth; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setIndex( int x1, int x2, int x3 ) +{ + this->ix1 = x1; + this->ix2 = x2; + this->ix3 = x3; +} +////////////////////////////////////////////////////////////////////////// +SPtr<DataSet3D> LBMKernel::getDataSet() const +{ + return this->dataSet; +} +////////////////////////////////////////////////////////////////////////// +LBMReal LBMKernel::getDeltaT() const +{ + return this->deltaT; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setDeltaT( LBMReal dt ) +{ + deltaT = dt; +} +////////////////////////////////////////////////////////////////////////// +bool LBMKernel::getCompressible() const +{ + return compressible; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setCompressible(bool val) +{ + compressible = val; +} +////////////////////////////////////////////////////////////////////////// +bool LBMKernel::getWithForcing() const +{ + return withForcing; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setWithForcing( bool val ) +{ + withForcing = val; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setBlock( SPtr<Block3D> block ) +{ + this->block = block; +} +////////////////////////////////////////////////////////////////////////// +SPtr<Block3D> LBMKernel::getBlock() const +{ + return block.lock(); +} +////////////////////////////////////////////////////////////////////////// +bool LBMKernel::getWithSpongeLayer() const +{ + return withSpongeLayer; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setWithSpongeLayer( bool val ) +{ + withSpongeLayer = val; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setSpongeLayer( const mu::Parser& parser ) +{ + this->checkFunction(parser); + this->muSpongeLayer = parser; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setSpongeLayer( const std::string& muParserString ) +{ + this->muSpongeLayer.SetExpr(muParserString); + this->checkFunction(muSpongeLayer); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setDataSet(SPtr<DataSet3D> dataSet) +{ + this->dataSet = dataSet; +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::swapDistributions() +{ + dataSet->getFdistributions()->swap(); +} +////////////////////////////////////////////////////////////////////////// +void LBMKernel::setNX(std::array<int, 3> nx) +{ + this->nx = nx; +} +////////////////////////////////////////////////////////////////////////// +std::array<int, 3> LBMKernel::getNX() +{ + return nx; +} +////////////////////////////////////////////////////////////////////////// +bool LBMKernel::isInsideOfDomain(const int& x1, const int& x2, const int& x3) const +{ + const SPtr<BCArray3D> bcArray = this->bcProcessor->getBCArray(); + return bcArray->isInsideOfDomain(x1, x2, x3, ghostLayerWidth); +} diff --git a/VirtualFluidsCore/LBM/LBMKernel.h b/VirtualFluidsCore/LBM/LBMKernel.h new file mode 100644 index 0000000000000000000000000000000000000000..b97ac3d8d6dbc6c6fc7d0612c6b3938ac395c721 --- /dev/null +++ b/VirtualFluidsCore/LBM/LBMKernel.h @@ -0,0 +1,139 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LBMKernel.h +//! \ingroup LBM +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef LBMKERNEL_H +#define LBMKERNEL_H + +#include <PointerDefinitions.h> +#include "LBMSystem.h" +#include "ILBMKernel.h" +#include <array> +#include <limits> +#include <MuParser/include/muParser.h> + +class BCProcessor; +class DataSet3D; +class Block3D; + +//! \brief A base class provides basic functionality for LBM kernel +class LBMKernel : public ILBMKernel, public enableSharedFromThis<LBMKernel> +{ +public: + typedef std::numeric_limits<LBMReal> LBMRealLim; +public: + LBMKernel(); + virtual ~LBMKernel(); + + virtual SPtr<LBMKernel> clone() = 0; + + virtual void calculate(int step) = 0; + + void setBCProcessor(SPtr<BCProcessor> bcp); + SPtr<BCProcessor> getBCProcessor() const; + + void setCollisionFactor(double collFactor); + double getCollisionFactor() const; + + void setGhostLayerWidth(int witdh); + int getGhostLayerWidth() const; + + void setDataSet(SPtr<DataSet3D> dataSet); + SPtr<DataSet3D> getDataSet() const; + + void setForcingX1(LBMReal forcingX1); + void setForcingX2(LBMReal forcingX2); + void setForcingX3(LBMReal forcingX3); + + void setForcingX1(const mu::Parser& parser); + void setForcingX2(const mu::Parser& parser); + void setForcingX3(const mu::Parser& parser); + + void setForcingX1(const std::string& muParserString); + void setForcingX2(const std::string& muParserString); + void setForcingX3(const std::string& muParserString); + + void setIndex(int x1, int x2, int x3); + + LBMReal getDeltaT() const; + void setDeltaT(LBMReal dt); + + bool getCompressible() const; + void setCompressible(bool val); + + bool getWithForcing() const; + void setWithForcing(bool val); + + bool getWithSpongeLayer() const; + void setWithSpongeLayer(bool val); + + void setSpongeLayer(const mu::Parser& parser); + void setSpongeLayer(const std::string& muParserString); + + void setBlock(SPtr<Block3D> block); + SPtr<Block3D> getBlock() const; + + bool isInsideOfDomain(const int &x1, const int &x2, const int &x3) const; + + void swapDistributions() override; + + void setNX(std::array<int, 3> nx); + std::array<int, 3> getNX(); + +protected: + SPtr<DataSet3D> dataSet; + SPtr<BCProcessor> bcProcessor; + LBMReal collFactor; + int ghostLayerWidth; + bool compressible; + + //forcing + bool withForcing; + mu::Parser muForcingX1; + mu::Parser muForcingX2; + mu::Parser muForcingX3; + int ix1, ix2, ix3; + LBMReal deltaT; + + //sponge layer + bool withSpongeLayer; + mu::Parser muSpongeLayer; + + WPtr<Block3D> block; + + std::array<int, 3> nx; + +private: + void checkFunction(mu::Parser fct); +}; + +#endif diff --git a/VirtualFluidsCore/LBM/LBMSystem.cpp b/VirtualFluidsCore/LBM/LBMSystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d025557036bdbc7642a1b6ca95ef4de242b6e95 --- /dev/null +++ b/VirtualFluidsCore/LBM/LBMSystem.cpp @@ -0,0 +1,39 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LBMSystem.cpp +//! \ingroup LBM +//! \author Sebastian Geller +//======================================================================================= + +#include "LBMSystem.h" + +namespace LBMSystem +{ + real SMAG_CONST = REAL_CAST(0.18); +} diff --git a/VirtualFluidsCore/LBM/LBMSystem.h b/VirtualFluidsCore/LBM/LBMSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..06569fe75c6f12b9dd785a6b61d9974d3ec810d0 --- /dev/null +++ b/VirtualFluidsCore/LBM/LBMSystem.h @@ -0,0 +1,95 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LBMSystem.h +//! \ingroup LBM +//! \author Sebastian Geller +//======================================================================================= +#ifndef LBMSYSTEM_H +#define LBMSYSTEM_H + +#include <cmath> +#include <string> +#include <iostream> + + +//! \brief namespace for global system-functions + +namespace LBMSystem +{ + +//#define SINGLEPRECISION + +#ifdef SINGLEPRECISION + typedef float real; + #define REAL_CAST(x) ( (LBMSystem::real)(x) ) +#else + typedef double real; + #define REAL_CAST(x) ( x ) +#endif + + extern real SMAG_CONST; + + ////////////////////////////////////////////////////////////////////////// + //!get LBM deltaT is equal LBM DeltaX + //!deltaT is dependent from grid level + //!for first grid level is deltaT = 1.0 + //!for next grid level 1/2 etc. + static real getDeltaT(int level) + { + return REAL_CAST(1.0/REAL_CAST(1<<level)); + } + + ////////////////////////////////////////////////////////////////////////// + //!calculate collision factor omega = 1.0/(3.0*viscosity/deltaT+0.5) + //!deltaT is dependent from grid level + //!for first grid level is deltaT = 1.0 + //!for next grid level 1/2 etc. + static real calcCollisionFactor(real viscosity, int level) + { + //return REAL_CAST(1.0/(3.0*viscosity/deltaT+0.5)); + return REAL_CAST(1.0/(3.0*viscosity/(1.0/REAL_CAST(1<<level))+0.5)); + } + + //!bulk viscosity + static real calcOmega2(real viscosity, int level) + { + return REAL_CAST(1.0/(4.5*viscosity/(1.0/REAL_CAST(1<<level))+0.5)); + } + //!bulk viscosity + static real calcOmega2(real viscosity, real deltaT) + { + return REAL_CAST(1.0/(4.5*viscosity/deltaT+0.5)); + } +} + +//some typedefs for global namespace +typedef LBMSystem::real LBMReal; + +#endif + diff --git a/VirtualFluidsCore/LBM/LBMUnitConverter.h b/VirtualFluidsCore/LBM/LBMUnitConverter.h new file mode 100644 index 0000000000000000000000000000000000000000..2b1eb8b4e6703b3204591e31666cf07ba42d9ad5 --- /dev/null +++ b/VirtualFluidsCore/LBM/LBMUnitConverter.h @@ -0,0 +1,190 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LBMUnitConverter.h +//! \ingroup LBM +//! \author Sören Freudiger +//======================================================================================= + +#ifndef LBMUNITCONVERTER_H +#define LBMUNITCONVERTER_H + +#include <iostream> +#include <iomanip> +#include <string> +#include <sstream> +#include <cmath> + +#include <basics/utilities/UbException.h> + +//! \brief A class provides converter for LB units <-> SI units +//! \details +//! \code +//! LBMUnitConverter conv( 100 /*L_World*/, 1484/*cs_water*/ , 1000/*rho_water*/ +//! , 1000/*L_LB*/ , 1./srqt(3.)/*cs_Lb*/, 1/*rho_Lb*/ ); +//! cout<<conv.toString()<<endl; +//! +//! cout<<"100m = "<< 100 * conv.getFactorLentghWToLb() << "dx " << std::endl; +//! cout<<"1000dx = "<< 1000 * conv.getFactorLentghLbToW() << "m " << std::endl; +//! +//! cout<<"25m/s = "<< 25 * conv.getFactorVelocityWToLb() << "dx/dt " << std::endl; +//! cout<<"0.04 dx/dt = "<< 0.04 * conv.getFactorVelocityLbToW() << "m/s " << std::endl; +//! \endcode +//! alternative +//! \code +//! LBMUnitConverter conv(, 100 /*L_World*/, LBMUnitConverter::WATER, 1000/*L_LB*/ ); +//! \endcode + +class LBMUnitConverter +{ +public: + + enum WORLD_MATERIAL { WATER = 0, SEAWWATER = 1, AIR_20C = 2, OIL = 3 }; + + LBMUnitConverter() : factorLengthLbToW(1.0), + factorTimeLbToW(1.0), + factorMassLbToW(1.0), + refRhoLb(1.0) + { + + } + + LBMUnitConverter( const double& refLengthWorld, const double& csWorld, const double& rhoWorld + , const double& refLengthLb , const double& csLb = 1.0/std::sqrt(3.0) , const double& rhoLb = 1.0 ) + { + this->init( refLengthWorld, csWorld, rhoWorld, csWorld, refLengthLb, rhoLb, csLb ); + + } + + LBMUnitConverter( const double& refLengthWorld, WORLD_MATERIAL worldMaterial + , const double& refLengthLb , const double& csLb = 1.0/std::sqrt(3.0) , const double& rhoLb = 1.0 ) + { + double csWorld; + double rhoWorld; + + if ( worldMaterial == WATER ) { csWorld = 1484/*m/s*/; rhoWorld = 1000/*kg/m^3*/; } + else if( worldMaterial == SEAWWATER) { csWorld = 1500/*m/s*/; rhoWorld = 1025/*kg/m^3*/; } + else if( worldMaterial == AIR_20C ) { csWorld = 343/*m/s*/; rhoWorld = 1.290/*kg/m^3*/; } + else if( worldMaterial == OIL ) { csWorld = 1740/*m/s*/; rhoWorld = 830/*kg/m^3*/; } + else throw UbException(UB_EXARGS,"unknown material"); + + this->init( refLengthWorld, csWorld, rhoWorld, csWorld, refLengthLb, rhoLb, csLb ); + + } + + virtual ~LBMUnitConverter() {} + + double getRefRhoLb() { return refRhoLb; } + + double getFactorLentghLbToW() { return factorLengthLbToW; } + double getFactorLentghWToLb() { return 1.0/this->getFactorLentghLbToW(); } + + double getFactorTimeLbToW() { return factorTimeLbToW; } + double getFactorTimeWToLb() { return 1.0/this->getFactorTimeLbToW(); } + + double getFactorVelocityLbToW() { return factorLengthLbToW/factorTimeLbToW; } + double getFactorVelocityWToLb() { return 1.0/this->getFactorVelocityLbToW(); } + + double getFactorViscosityLbToW() { return factorLengthLbToW*factorLengthLbToW/factorTimeLbToW; } + double getFactorViscosityWToLb() { return 1.0/this->getFactorViscosityLbToW(); } + + double getFactorDensityLbToW() { return this->factorMassLbToW/std::pow(factorLengthLbToW,3.0); } + double getFactorDensityWToLb() { return 1.0/this->getFactorDensityLbToW(); } + + double getFactorPressureLbToW() { return this->factorMassLbToW/(std::pow(factorTimeLbToW,2.0)*factorLengthLbToW); } + double getFactorPressureWToLb() { return 1.0/this->getFactorPressureLbToW(); } + + double getFactorMassLbToW() { return this->factorMassLbToW; } + double getFactorMassWToLb() { return 1.0/this->getFactorMassLbToW(); } + + double getFactorForceLbToW() { return factorMassLbToW*factorLengthLbToW/(factorTimeLbToW*factorTimeLbToW); } + double getFactorForceWToLb() { return 1.0/this->getFactorForceLbToW(); } + + double getFactorAccLbToW() { return factorLengthLbToW/(factorTimeLbToW*factorTimeLbToW); } + double getFactorAccWToLb() { return 1.0/this->getFactorAccLbToW(); } + + double getFactorTimeLbToW(double deltaX) const { return factorTimeWithoutDx * deltaX; } + + /*==========================================================*/ + friend inline std::ostream& operator << (std::ostream& os, LBMUnitConverter c) + { + os<<c.toString(); + return os; + } + /*==========================================================*/ + std::string toString() + { + std::ostringstream out; + out<<"LB --> WORLD" << std::endl; + out<<" * lentgh 1[dx ] = " << std::setw(12) << this->getFactorLentghLbToW() << " [m ] " << std::endl; + out<<" * time 1[dt ] = " << std::setw(12) << this->getFactorTimeLbToW() << " [s ] " << std::endl; + out<<" * mass 1[mass] = " << std::setw(12) << this->getFactorMassLbToW() << " [kg ] " << std::endl; + out<<std::endl; + out<<"WORLD --> LB" << std::endl; + out<<" * lentgh 1[m ] = " << std::setw(12) << this->getFactorLentghWToLb() << " [dx ] " << std::endl; + out<<" * time 1[s ] = " << std::setw(12) << this->getFactorTimeWToLb() << " [dt ] " << std::endl; + out<<" * mass 1[kg ] = " << std::setw(12) << this->getFactorMassWToLb() << " [mass] " << std::endl; + out<<std::endl; + out<<"LB --> WORLD (combined units)" << std::endl; + out<<" * velocity 1 [dx/dt ] = " << std::setw(12) << this->getFactorVelocityLbToW() << " [m/s ]" << std::endl; + out<<" * density 1 [mass/dx^3] = " << std::setw(12) << this->getFactorDensityLbToW() << " [kg/m^3 ]" << std::endl; + out<<" * pressure 1 [F_lb/dx^2] = " << std::setw(12) << this->getFactorPressureLbToW() << " [N/m^2 ]" << std::endl; + out<<" * viscosity 1 [dx^2/dt ] = " << std::setw(12) << this->getFactorViscosityLbToW() << " [m^2/s ]" << std::endl; + out<<" * force 1 [F_lb ] = " << std::setw(12) << this->getFactorForceLbToW() << " [N ]" << std::endl; + out<<" * acceleration 1 [dx/dt^2 ] = " << std::setw(12) << this->getFactorAccLbToW() << " [m/s^2 ]" << std::endl; + out<<std::endl; + out<<"WORLD --> LB (combined units)" << std::endl; + out<<" * velocity 1 [m/s ] = " << std::setw(12) << this->getFactorVelocityWToLb() << " [dx/dt ]" << std::endl; + out<<" * density 1 [kg/m^3 ] = " << std::setw(12) << this->getFactorDensityWToLb() << " [mass/dx^3]" << std::endl; + out<<" * pressure 1 [N/m^2 ] = " << std::setw(12) << this->getFactorPressureWToLb() << " [F_lb/dx^2]" << std::endl; + out<<" * viscosity 1 [m^2/s ] = " << std::setw(12) << this->getFactorViscosityWToLb() << " [dx^2/dt ]" << std::endl; + out<<" * force 1 [N ] = " << std::setw(12) << this->getFactorForceWToLb() << " [F_lb ]" << std::endl; + out<<" * acceleration 1 [m/s^2 ] = " << std::setw(12) << this->getFactorAccWToLb() << " [dx/dt^2 ]" << std::endl; + + return out.str(); + } + + void init( const double& refLengthWorld, const double& csWorld, const double& rhoWorld, const double& vWorld, + const double& refLengthLb, const double& rhoLb, const double& vLb ) + { + factorLengthLbToW = refLengthWorld / refLengthLb; + factorTimeLbToW = vLb / vWorld * factorLengthLbToW; + factorMassLbToW = rhoWorld/rhoLb*factorLengthLbToW*factorLengthLbToW*factorLengthLbToW; + factorTimeWithoutDx=vLb/vWorld; + this->refRhoLb = rhoLb; + } + + protected: + double factorLengthLbToW; + double factorTimeLbToW; + double factorMassLbToW; + double refRhoLb; + double factorTimeWithoutDx; +}; + +#endif //LBMUNITCONVERTER_H diff --git a/VirtualFluidsCore/Parallel/CMakePackage.txt b/VirtualFluidsCore/Parallel/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Parallel/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Parallel/Communicator.cpp b/VirtualFluidsCore/Parallel/Communicator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a53a558f4b72ccc97191940918e523ae217443ab --- /dev/null +++ b/VirtualFluidsCore/Parallel/Communicator.cpp @@ -0,0 +1,45 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Communicator.cpp +//! \ingroup Parallel +//! \author Konstantin Kutscher +//======================================================================================= + +#include "Communicator.h" +#include <basics/utilities/UbException.h> + +SPtr<Communicator> Communicator::instance = SPtr<Communicator>(); +////////////////////////////////////////////////////////////////////////// +SPtr<Communicator> Communicator::getInstance() +{ + if( !instance ) + UB_THROW(UbException(UB_EXARGS,"Communicator isn't initialized correctly! You can not create a new instance of abstract Communicator class!")); + return instance; +} + diff --git a/VirtualFluidsCore/Parallel/Communicator.h b/VirtualFluidsCore/Parallel/Communicator.h new file mode 100644 index 0000000000000000000000000000000000000000..828c9f5c0f42e8c9bc9ac1a33cc298725b3509dc --- /dev/null +++ b/VirtualFluidsCore/Parallel/Communicator.h @@ -0,0 +1,60 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Communicator.h +//! \ingroup Parallel +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef COMMUNICATOR_H +#define COMMUNICATOR_H + +#include <vector> +#include <string> + +#include <PointerDefinitions.h> + +//! \brief An abstract class for communication between processes in parallel computation +class Communicator +{ +public: + virtual ~Communicator(){} + static SPtr<Communicator> getInstance(); + virtual int getProcessID() = 0; + virtual int getNumberOfProcesses() = 0; + virtual bool isRoot() = 0; + virtual int getRoot() = 0; + virtual int getProcessRoot() = 0; +protected: + Communicator(){} + Communicator( const Communicator& ){} + static SPtr<Communicator> instance; +}; + +#endif + diff --git a/VirtualFluidsCore/Parallel/NullCommunicator.cpp b/VirtualFluidsCore/Parallel/NullCommunicator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcd745d36279acf3b72773a92e1e6ad878d93915 --- /dev/null +++ b/VirtualFluidsCore/Parallel/NullCommunicator.cpp @@ -0,0 +1,75 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NullCommunicator.cpp +//! \ingroup Parallel +//! \author Konstantin Kutscher +//======================================================================================= + +#include "NullCommunicator.h" + +NullCommunicator::NullCommunicator() +{ +} +////////////////////////////////////////////////////////////////////////// +NullCommunicator::~NullCommunicator() +{ +} +////////////////////////////////////////////////////////////////////////// +SPtr<Communicator> NullCommunicator::getInstance() +{ + if( !Communicator::instance ) + Communicator::instance = SPtr<Communicator>(new NullCommunicator()); + return Communicator::instance; +} +////////////////////////////////////////////////////////////////////////// +int NullCommunicator::getProcessID() +{ + return 0; +} +////////////////////////////////////////////////////////////////////////// +int NullCommunicator::getNumberOfProcesses() +{ + return 1; +} +////////////////////////////////////////////////////////////////////////// +bool NullCommunicator::isRoot() +{ + return true; +} +////////////////////////////////////////////////////////////////////////// +int NullCommunicator::getRoot() +{ + return 0; +} +////////////////////////////////////////////////////////////////////////// +int NullCommunicator::getProcessRoot() +{ + return 0; +} + diff --git a/VirtualFluidsCore/Parallel/NullCommunicator.h b/VirtualFluidsCore/Parallel/NullCommunicator.h new file mode 100644 index 0000000000000000000000000000000000000000..b554ebc00bbecf5442fcb5a5c2b410ae71af0152 --- /dev/null +++ b/VirtualFluidsCore/Parallel/NullCommunicator.h @@ -0,0 +1,60 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file NullCommunicator.h +//! \ingroup Parallel +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef NullCommunicator_H +#define NullCommunicator_H + +#include "Communicator.h" + +#include <PointerDefinitions.h> + +//! \brief A class implements Communicator for shared memory. +//! \details NullCommunicator is only a place-holder. It is only one process in shared memory. +class NullCommunicator : public Communicator +{ + private: + NullCommunicator(); + NullCommunicator( const NullCommunicator& ){} +public: + ~NullCommunicator(); + static SPtr<Communicator> getInstance(); + int getProcessID(); + int getNumberOfProcesses(); + bool isRoot(); + int getRoot(); + int getProcessRoot(); +protected: +private: +}; + +#endif diff --git a/VirtualFluidsCore/PointerDefinitions.h b/VirtualFluidsCore/PointerDefinitions.h new file mode 100644 index 0000000000000000000000000000000000000000..f5cabd1ff2f423413aca55cd6bcd8fb4fff806e9 --- /dev/null +++ b/VirtualFluidsCore/PointerDefinitions.h @@ -0,0 +1,53 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PointerDefinitions.h +//! \ingroup Core +//! \author Soeren Peters +//======================================================================================= +#ifndef SHARED_POINTER_H +#define SHARED_POINTER_H + +#include <memory> + +template <class T> +using SPtr = std::shared_ptr<T>; + +template <class T> +using WPtr = std::weak_ptr<T>; + +template <class T> +using UPtr = std::unique_ptr<T>; + +template <class T> +using RPtr = T*; + +template <class T> +using enableSharedFromThis = std::enable_shared_from_this<T>; + +#endif diff --git a/VirtualFluidsCore/Utilities/CMakePackage.txt b/VirtualFluidsCore/Utilities/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Utilities/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Utilities/MemoryUtil.h b/VirtualFluidsCore/Utilities/MemoryUtil.h new file mode 100644 index 0000000000000000000000000000000000000000..c8306083b15b5168702d028ff1687eb0938bc9ea --- /dev/null +++ b/VirtualFluidsCore/Utilities/MemoryUtil.h @@ -0,0 +1,162 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file MemoryUtil.h +//! \ingroup Utilities +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef _MEMORYUTIL_H_ +#define _MEMORYUTIL_H_ + +#if defined(_WIN32) || defined(_WIN64) + #define MEMORYUTIL_WINDOWS + #include "windows.h" + #include "psapi.h" + #pragma comment(lib, "psapi.lib") +#elif defined __APPLE__ +#define MEMORYUTIL_APPLE + #include "sys/types.h" + #include "sys/sysctl.h" + #include "stdlib.h" + #include "stdio.h" + #include "string.h" +#elif (defined(__amd64) || defined(__amd64__) || defined(__unix__)) && !defined(__AIX__) + #define MEMORYUTIL_LINUX + #include "sys/types.h" + #include "sys/sysinfo.h" + #include "stdlib.h" + #include "stdio.h" + #include "string.h" +#else + #error "MemoryUtil::UnknownMachine" +#endif + +#if defined(__CYGWIN__) + #define MEMORYUTIL_CYGWIN +#endif +////////////////////////////////////////////////////////////////////////// +//MemoryUtil +////////////////////////////////////////////////////////////////////////// +namespace Utilities +{ +////////////////////////////////////////////////////////////////////////// + static long long getTotalPhysMem() + { + #if defined(MEMORYUTIL_WINDOWS) + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + DWORDLONG totalPhysMem = memInfo.ullTotalPhys; + #elif defined(MEMORYUTIL_LINUX) + struct sysinfo memInfo; + sysinfo (&memInfo); + long long totalPhysMem = memInfo.totalram; + //Multiply in next statement to avoid int overflow on right hand side... + totalPhysMem *= memInfo.mem_unit; + #elif defined(MEMORYUTIL_APPLE) + long long totalPhysMem = 0; + #else + #error "MemoryUtil::getTotalPhysMem - UnknownMachine" + #endif + + return (long long)totalPhysMem; + } +////////////////////////////////////////////////////////////////////////// + static long long getPhysMemUsed() + { + #if defined(MEMORYUTIL_WINDOWS) + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys; + #elif defined(MEMORYUTIL_LINUX) + struct sysinfo memInfo; + sysinfo (&memInfo); + long long physMemUsed = memInfo.totalram - memInfo.freeram; + //Multiply in next statement to avoid int overflow on right hand side... + physMemUsed *= memInfo.mem_unit; + #elif defined(MEMORYUTIL_APPLE) + long long physMemUsed = 0; + #else + #error "MemoryUtil::getPhysMemUsed - UnknownMachine" + #endif + + return (long long)physMemUsed; + } +////////////////////////////////////////////////////////////////////////// +#if defined(MEMORYUTIL_LINUX) || defined(MEMORYUTIL_APPLE) || defined(MEMORYUTIL_CYGWIN) + static int parseLine(char* line){ + int i = strlen(line); + while (*line < '0' || *line > '9') line++; + line[i-3] = '\0'; + i = atoi(line); + return i; + } + + static int getValue(){ //Note: this value is in KB! + FILE* file = fopen("/proc/self/status", "r"); + int result = -1; + char line[128]; + + + while (fgets(line, 128, file) != NULL){ + if (strncmp(line, "VmRSS:", 6) == 0){ + result = parseLine(line); + break; + } + } + fclose(file); + return result; + } +#endif +////////////////////////////////////////////////////////////////////////// + static long long getPhysMemUsedByMe() + { + #if defined(MEMORYUTIL_WINDOWS) && !defined(__CYGWIN__) + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); + SIZE_T physMemUsedByMe = pmc.WorkingSetSize; + #elif defined(MEMORYUTIL_LINUX) + long long physMemUsedByMe = (long long)getValue() * (long long)1024; + #elif defined(MEMORYUTIL_APPLE) + long long physMemUsedByMe = 0; + #elif defined(MEMORYUTIL_CYGWIN) + long long physMemUsedByMe = (long long)getValue() * (long long)1024; + #else + #error "MemoryUtil::getPhysMemUsedByMe - UnknownMachine" + #endif + + return (long long)physMemUsedByMe; + } +////////////////////////////////////////////////////////////////////////// + +} + +#endif + diff --git a/VirtualFluidsCore/Visitors/Block3DVisitor.h b/VirtualFluidsCore/Visitors/Block3DVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..0a030629e680d7929e2a1b7e47cb8a802b087e85 --- /dev/null +++ b/VirtualFluidsCore/Visitors/Block3DVisitor.h @@ -0,0 +1,90 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Block3DVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher, Soeren Freudiger, Sebastian Geller +//======================================================================================= + +#ifndef Block3DVisitor_h +#define Block3DVisitor_h + +#include <PointerDefinitions.h> + +class Block3D; +class Grid3D; + +//! Abstract class provides interface for visitor design pettern +class Block3DVisitor +{ +public: + Block3DVisitor() : startLevel(-1), stopLevel(-1) + { + } + + Block3DVisitor(int startLevel, int stopLevel) : startLevel(startLevel), stopLevel(stopLevel) + { + } + + virtual ~Block3DVisitor() + { + } + + virtual void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) = 0; + + int getStartLevel() const; + int getStopLevel() const; + void setStartLevel(int level); + void setStopLevel(int level); + +private: + int startLevel; + int stopLevel; +}; +////////////////////////////////////////////////////////////////////////// +inline int Block3DVisitor::getStartLevel() const +{ + return this->startLevel; +} +////////////////////////////////////////////////////////////////////////// +inline int Block3DVisitor::getStopLevel() const +{ + return this->stopLevel; +} +////////////////////////////////////////////////////////////////////////// +inline void Block3DVisitor::setStartLevel(int level) +{ + this->startLevel = level; +} +////////////////////////////////////////////////////////////////////////// +inline void Block3DVisitor::setStopLevel(int level) +{ + this->stopLevel = level; +} + +#endif diff --git a/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.cpp b/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5135f2db7fc14fc33afe5c0d2b12a79ab58af91c --- /dev/null +++ b/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.cpp @@ -0,0 +1,130 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BoundaryConditionsBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "BoundaryConditionsBlockVisitor.h" +#include "LBMKernel.h" +#include "BCProcessor.h" +#include "Grid3DSystem.h" +#include "D3Q27EsoTwist3DSplittedVector.h" +#include "DataSet3D.h" +#include "Grid3D.h" +#include "BCAdapter.h" +#include "Block3D.h" +#include "BCArray3D.h" + +BoundaryConditionsBlockVisitor::BoundaryConditionsBlockVisitor() : +Block3DVisitor(0, Grid3DSystem::MAXLEVEL) +{ + +} +////////////////////////////////////////////////////////////////////////// +BoundaryConditionsBlockVisitor::~BoundaryConditionsBlockVisitor() +{ + +} +////////////////////////////////////////////////////////////////////////// +void BoundaryConditionsBlockVisitor::visit(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + if (block->getRank() == grid->getRank()) + { + SPtr<ILBMKernel> kernel = block->getKernel(); + + if (!kernel) + { + throw UbException(UB_EXARGS, "LBMKernel in " + block->toString() + "is not exist!"); + } + + SPtr<BCProcessor> bcProcessor = kernel->getBCProcessor(); + + if (!bcProcessor) + { + throw UbException(UB_EXARGS,"Boundary Conditions Processor is not exist!" ); + } + + SPtr<BCArray3D> bcArray = bcProcessor->getBCArray(); + + bool compressible = kernel->getCompressible(); + double collFactor = kernel->getCollisionFactor(); + int level = block->getLevel(); + + int minX1 = 0; + int minX2 = 0; + int minX3 = 0; + int maxX1 = (int)bcArray->getNX1(); + int maxX2 = (int)bcArray->getNX2(); + int maxX3 = (int)bcArray->getNX3(); + SPtr<BoundaryConditions> bcPtr; + + bcProcessor->clearBC(); + + SPtr<DistributionArray3D> distributions = kernel->getDataSet()->getFdistributions(); + + for (int x3 = minX3; x3 < maxX3; x3++) + { + for (int x2 = minX2; x2 < maxX2; x2++) + { + for (int x1 = minX1; x1 < maxX1; x1++) + { + if (!bcArray->isSolid(x1, x2, x3) && !bcArray->isUndefined(x1, x2, x3)) + { + if ((bcPtr = bcArray->getBC(x1, x2, x3)) != NULL) + { + char alg = bcPtr->getBcAlgorithmType(); + SPtr<BCAlgorithm> bca = bcMap[alg]; + + if (bca) + { + bca = bca->clone(); + bca->setNodeIndex(x1, x2, x3); + bca->setBcPointer(bcPtr); + bca->addDistributions(distributions); + bca->setCollFactor(collFactor); + bca->setCompressible(compressible); + bca->setBcArray(bcArray); + bcProcessor->addBC(bca); + } + } + } + } + } + } + } +} +////////////////////////////////////////////////////////////////////////// +void BoundaryConditionsBlockVisitor::addBC(SPtr<BCAdapter> bc) +{ + bcMap.insert(std::make_pair(bc->getBcAlgorithmType(), bc->getAlgorithm())); +} + + + diff --git a/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.h b/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..0a8023fb074e4ebe6b9a277896eefaa93b53ec6c --- /dev/null +++ b/VirtualFluidsCore/Visitors/BoundaryConditionsBlockVisitor.h @@ -0,0 +1,61 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BoundaryConditionsBlockVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef BoundaryConditionBlockVisitor_h__ +#define BoundaryConditionBlockVisitor_h__ + +#include <map> +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" + + +class Grid3D; +class Block3D; +class BCAlgorithm; +class BCAdapter; + +//! \brief set boundary conditions +class BoundaryConditionsBlockVisitor : public Block3DVisitor +{ +public: + BoundaryConditionsBlockVisitor(); + virtual ~BoundaryConditionsBlockVisitor(); + + void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override; + void addBC(SPtr<BCAdapter> bc); +protected: +private: + std::map<char, SPtr<BCAlgorithm> > bcMap; +}; +#endif // BoundaryConditionBlockVisitor_h__ diff --git a/VirtualFluidsCore/Visitors/CMakePackage.txt b/VirtualFluidsCore/Visitors/CMakePackage.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8416f010d2a7de30b8f70c9abf19a96dd8cf8f --- /dev/null +++ b/VirtualFluidsCore/Visitors/CMakePackage.txt @@ -0,0 +1,2 @@ +GET_FILENAME_COMPONENT( CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES) diff --git a/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp b/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fce3b53078b62a21af4a0374ab643d740af5ecd --- /dev/null +++ b/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp @@ -0,0 +1,111 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GenBlocksGridVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "GenBlocksGridVisitor.h" +#include "Grid3DSystem.h" +#include "CoordinateTransformation3D.h" +#include "Block3D.h" +#include "Grid3D.h" + +#include <geometry3d/GbObject3D.h> + +GenBlocksGridVisitor::GenBlocksGridVisitor(SPtr<GbObject3D> boundingBox) : + boundingBox(boundingBox) +{ + +} +////////////////////////////////////////////////////////////////////////// +void GenBlocksGridVisitor::visit(const SPtr<Grid3D> grid) +{ + double orgX1 = boundingBox->getX1Minimum(); + double orgX2 = boundingBox->getX2Minimum(); + double orgX3 = boundingBox->getX3Minimum(); + + double dx = grid->getDeltaX(0); + + UbTupleInt3 blockNX = grid->getBlockNX(); + + double blockLentghX1 = (double)val<1>(blockNX)*dx; + double blockLentghX2 = (double)val<2>(blockNX)*dx; + double blockLentghX3 = (double)val<3>(blockNX)*dx; + + SPtr<CoordinateTransformation3D> trafo(new CoordinateTransformation3D(orgX1, orgX2, orgX3, blockLentghX1, blockLentghX2, blockLentghX3)); + grid->setCoordinateTransformator(trafo); + + genBlocks(grid); +} +////////////////////////////////////////////////////////////////////////// +void GenBlocksGridVisitor::fillExtentWithBlocks( SPtr<Grid3D> grid ) +{ + for(int x3 = val<3>(minInd); x3 < val<3>(maxInd); x3++) + { + for(int x2 = val<2>(minInd); x2 < val<2>(maxInd); x2++) + { + for(int x1 = val<1>(minInd); x1 < val<1>(maxInd); x1++) + { + SPtr<Block3D> block( new Block3D(x1,x2,x3,0) ); + grid->addBlock(block); + } + } + } +} +////////////////////////////////////////////////////////////////////////// +void GenBlocksGridVisitor::genBlocks(SPtr<Grid3D> grid) +{ + minInd = grid->getBlockIndexes(boundingBox->getX1Minimum(), boundingBox->getX2Minimum(), boundingBox->getX3Minimum()); + double geoMaxX1 = boundingBox->getX1Maximum(); + double geoMaxX2 = boundingBox->getX2Maximum(); + double geoMaxX3 = boundingBox->getX3Maximum(); + maxInd = grid->getBlockIndexes(geoMaxX1, geoMaxX2, geoMaxX3); + UbTupleDouble3 blockCoord = grid->getBlockWorldCoordinates(static_cast<int>(val<1>(maxInd)), static_cast<int>(val<2>(maxInd)), static_cast<int>(val<3>(maxInd)), 0); + //if (geoMaxX1 > val<1>(blockCoord)) + // val<1>(maxInd) += 1; + //if (geoMaxX2 > val<2>(blockCoord)) + // val<2>(maxInd) += 1; + //if (geoMaxX3 > val<3>(blockCoord)) + // val<3>(maxInd) += 1; + + double dx = grid->getDeltaX(0); + if (fabs(geoMaxX1-val<1>(blockCoord)) > dx) + val<1>(maxInd) += 1; + if (fabs(geoMaxX2-val<2>(blockCoord)) > dx) + val<2>(maxInd) += 1; + if (fabs(geoMaxX3-val<3>(blockCoord)) > dx) + val<3>(maxInd) += 1; + + this->fillExtentWithBlocks(grid); + + grid->setNX1(val<1>(maxInd)); + grid->setNX2(val<2>(maxInd)); + grid->setNX3(val<3>(maxInd)); +} diff --git a/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h b/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..a80e8a626ac44a819cbcc6e1af2068c8a6988a51 --- /dev/null +++ b/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h @@ -0,0 +1,62 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GenBlocksGridVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef GenBlocksGridVisitor_h +#define GenBlocksGridVisitor_h + +#include <PointerDefinitions.h> + +#include <basics/utilities/UbTuple.h> + +#include "Grid3DVisitor.h" + +class GbObject3D; +class Grid3D; + +//! \brief generate blocks +class GenBlocksGridVisitor : public Grid3DVisitor +{ +public: + GenBlocksGridVisitor(SPtr<GbObject3D> boundingBox); + virtual ~GenBlocksGridVisitor(){} + + void visit(SPtr<Grid3D> grid); + +private: + UbTupleInt3 minInd, maxInd; + SPtr<GbObject3D> boundingBox; + void fillExtentWithBlocks(SPtr<Grid3D> grid); + void genBlocks(SPtr<Grid3D> grid); +}; + +#endif diff --git a/VirtualFluidsCore/Visitors/Grid3DVisitor.h b/VirtualFluidsCore/Visitors/Grid3DVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..5d2117f8b27880645606c2dc7a1457209b38a9b1 --- /dev/null +++ b/VirtualFluidsCore/Visitors/Grid3DVisitor.h @@ -0,0 +1,52 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Grid3DVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher, Soeren Freudiger, Sebastian Geller +//======================================================================================= + +#ifndef Grid3DVisitor_h +#define Grid3DVisitor_h + +#include <PointerDefinitions.h> + + +class Grid3D; + +//! Abstract class provides interface for visitor design pettern +class Grid3DVisitor +{ +public: + Grid3DVisitor() {} + virtual ~Grid3DVisitor() {} + + virtual void visit(SPtr<Grid3D> grid) = 0; +}; + +#endif diff --git a/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp b/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ecb9041b1cca71e5cfa3839897fe87049242804 --- /dev/null +++ b/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp @@ -0,0 +1,328 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InitDistributionsBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher, Soeren Freudiger +//======================================================================================= + +#include "InitDistributionsBlockVisitor.h" +#include "LBMKernel.h" +#include "BCProcessor.h" +#include "Grid3DSystem.h" +#include "DataSet3D.h" +#include "EsoTwist3D.h" +#include "Grid3D.h" +#include "Block3D.h" +#include "BCArray3D.h" + +InitDistributionsBlockVisitor::InitDistributionsBlockVisitor() + : Block3DVisitor(0, Grid3DSystem::MAXLEVEL) +{ + this->setVx1(0.0); + this->setVx2(0.0); + this->setVx3(0.0); + this->setRho(0.0); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx1( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muVx1 = parser; +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx2( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muVx2 = parser; +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx3( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muVx3 = parser; +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setRho( const mu::Parser& parser) +{ + this->checkFunction(parser); + this->muRho = parser; +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx1( const std::string& muParserString) +{ + this->muVx1.SetExpr(muParserString); + this->checkFunction(muVx1); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx2( const std::string& muParserString) +{ + this->muVx2.SetExpr(muParserString); + this->checkFunction(muVx2); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx3( const std::string& muParserString) +{ + this->muVx3.SetExpr(muParserString); + this->checkFunction(muVx3); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setRho( const std::string& muParserString) +{ + this->muRho.SetExpr(muParserString); + this->checkFunction(muRho); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx1( LBMReal vx1 ) +{ + this->muVx1.SetExpr( UbSystem::toString(vx1,D3Q27RealLim::digits10) ); + this->checkFunction(muVx1); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx2( LBMReal vx2 ) +{ + this->muVx2.SetExpr( UbSystem::toString(vx2,D3Q27RealLim::digits10) ); + this->checkFunction(muVx2); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setVx3( LBMReal vx3 ) +{ + this->muVx3.SetExpr( UbSystem::toString(vx3,D3Q27RealLim::digits10) ); + this->checkFunction(muVx3); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::setRho( LBMReal rho ) +{ + this->muRho.SetExpr( UbSystem::toString(rho,D3Q27RealLim::digits10) ); + this->checkFunction(muRho); +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::visit(const SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + using namespace D3Q27System; + + if(!block) UB_THROW( UbException(UB_EXARGS,"block is not exist") ); + + //UbTupleDouble3 blockLengths = grid->getBlockLengths(block); + //UbTupleDouble3 nodeOffset = grid->getNodeOffset(block); + double dx = grid->getDeltaX(block); + + //define vars for functions + mu::value_type x1,x2,x3; + this->muVx1.DefineVar("x1",&x1); this->muVx1.DefineVar("x2",&x2); this->muVx1.DefineVar("x3",&x3); + this->muVx2.DefineVar("x1",&x1); this->muVx2.DefineVar("x2",&x2); this->muVx2.DefineVar("x3",&x3); + this->muVx3.DefineVar("x1",&x1); this->muVx3.DefineVar("x2",&x2); this->muVx3.DefineVar("x3",&x3); + this->muRho.DefineVar("x1",&x1); this->muRho.DefineVar("x2",&x2); this->muRho.DefineVar("x3",&x3); + + //Funktionszeiger + typedef void (*CalcFeqsFct)(LBMReal* const& /*feq[27]*/,const LBMReal& /*(d)rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/); + CalcFeqsFct calcFeqsFct = NULL; + + LBMReal vx1,vx2,vx3,rho; + + int gridRank = grid->getRank(); + int blockRank = block->getRank(); + + if (blockRank == gridRank && block->isActive()) + { + SPtr<ILBMKernel> kernel = block->getKernel(); + if (!kernel) + throw UbException(UB_EXARGS, "The LBM kernel isn't exist in block: "+block->toString()); + + if(kernel->getCompressible()) + calcFeqsFct = &D3Q27System::calcCompFeq; + else + calcFeqsFct = &D3Q27System::calcIncompFeq; + + //UbTupleDouble3 org = grid->getBlockWorldCoordinates(block); + + SPtr<BCArray3D> bcArray = kernel->getBCProcessor()->getBCArray(); + SPtr<DistributionArray3D> distributions = kernel->getDataSet()->getFdistributions(); + + LBMReal o = kernel->getCollisionFactor(); + + LBMReal f[D3Q27System::ENDF+1]; + + size_t nx1 = distributions->getNX1(); + size_t nx2 = distributions->getNX2(); + size_t nx3 = distributions->getNX3(); + + for(int ix3=0; ix3<bcArray->getNX3(); ix3++) + for(int ix2=0; ix2<bcArray->getNX2(); ix2++) + for(int ix1=0; ix1<bcArray->getNX1(); ix1++) + { + Vector3D coords = grid->getNodeCoordinates(block, ix1, ix2, ix3); + x1 = coords[0]; + x2 = coords[1]; + x3 = coords[2]; + + vx1 = muVx1.Eval(); + vx2 = muVx2.Eval(); + vx3 = muVx3.Eval(); + rho = muRho.Eval(); + + //x-derivative + double deltaX=dx*0.5; + x1 = coords[0]+deltaX; + double vx1Plusx1 = muVx1.Eval(); + double vx2Plusx1 = muVx2.Eval(); + double vx3Plusx1 = muVx3.Eval(); + + x1 = coords[0]-deltaX; + double vx1Minusx1 = muVx1.Eval(); + double vx2Minusx1 = muVx2.Eval(); + double vx3Minusx1 = muVx3.Eval(); + + //y-derivative + x1 = coords[0]; + x2 = coords[1]+deltaX; + double vx1Plusx2 = muVx1.Eval(); + double vx2Plusx2 = muVx2.Eval(); + double vx3Plusx2 = muVx3.Eval(); + + x2 = coords[1]-deltaX; + double vx1Minusx2 = muVx1.Eval(); + double vx2Minusx2 = muVx2.Eval(); + double vx3Minusx2 = muVx3.Eval(); + + //z-derivative + x2 = coords[1]; + x3 = coords[2]+deltaX; + double vx1Plusx3 = muVx1.Eval(); + double vx2Plusx3 = muVx2.Eval(); + double vx3Plusx3 = muVx3.Eval(); + + x3 = coords[2]-deltaX; + double vx1Minusx3 = muVx1.Eval(); + double vx2Minusx3 = muVx2.Eval(); + double vx3Minusx3 = muVx3.Eval(); + + double ax=(vx1Plusx1-vx1Minusx1)/(2.0*deltaX)*dx; + double bx=(vx2Plusx1-vx2Minusx1)/(2.0*deltaX)*dx; + double cx=(vx3Plusx1-vx3Minusx1)/(2.0*deltaX)*dx; + + double ay=(vx1Plusx2-vx1Minusx2)/(2.0*deltaX)*dx; + double by=(vx2Plusx2-vx2Minusx2)/(2.0*deltaX)*dx; + double cy=(vx3Plusx2-vx3Minusx2)/(2.0*deltaX)*dx; + + double az=(vx1Plusx3-vx1Minusx3)/(2.0*deltaX)*dx; + double bz=(vx2Plusx3-vx2Minusx3)/(2.0*deltaX)*dx; + double cz=(vx3Plusx3-vx3Minusx3)/(2.0*deltaX)*dx; + double eps_new=1.0; + LBMReal op = 1.; + + LBMReal feq[27]; + + calcFeqsFct(feq,rho,vx1,vx2,vx3); + + double f_E = eps_new *((5.*ax*o + 5.*by*o + 5.*cz*o - 8.*ax*op + 4.*by*op + 4.*cz*op)/(54.*o*op)); + double f_N = f_E + eps_new *((2.*(ax - by))/(9.*o)); + double f_T = f_E + eps_new *((2.*(ax - cz))/(9.*o)); + double f_NE = eps_new *(-(5.*cz*o + 3.*(ay + bx)*op - 2.*cz*op + ax*(5.*o + op) + by*(5.*o + op))/(54.*o*op)); + double f_SE = f_NE + eps_new *(( ay + bx )/(9.*o)); + double f_TE = eps_new *(-(5.*cz*o + by*(5.*o - 2.*op) + 3.*(az + cx)*op + cz*op + ax*(5.*o + op))/(54.*o*op)); + double f_BE = f_TE + eps_new *(( az + cx )/(9.*o)); + double f_TN = eps_new *(-(5.*ax*o + 5.*by*o + 5.*cz*o - 2.*ax*op + by*op + 3.*bz*op + 3.*cy*op + cz*op)/(54.*o*op)); + double f_BN = f_TN + eps_new *(( bz + cy )/(9.*o)); + double f_ZERO = eps_new *((5.*(ax + by + cz))/(9.*op)); + double f_TNE = eps_new *(-(ay + az + bx + bz + cx + cy)/(72.*o)); + double f_TSW = - eps_new *((ay + bx)/(36.*o)) - f_TNE; + double f_TSE = - eps_new *((az + cx)/(36.*o)) - f_TNE; + double f_TNW = - eps_new *((bz + cy)/(36.*o)) - f_TNE; + + + f[E] = f_E + feq[E]; + f[W] = f_E + feq[W]; + f[N] = f_N + feq[N]; + f[S] = f_N + feq[S]; + f[T] = f_T + feq[T]; + f[B] = f_T + feq[B]; + f[NE] = f_NE + feq[NE]; + f[SW] = f_NE + feq[SW]; + f[SE] = f_SE + feq[SE]; + f[NW] = f_SE + feq[NW]; + f[TE] = f_TE + feq[TE]; + f[BW] = f_TE + feq[BW]; + f[BE] = f_BE + feq[BE]; + f[TW] = f_BE + feq[TW]; + f[TN] = f_TN + feq[TN]; + f[BS] = f_TN + feq[BS]; + f[BN] = f_BN + feq[BN]; + f[TS] = f_BN + feq[TS]; + f[TNE] = f_TNE + feq[TNE]; + f[TNW] = f_TNW + feq[TNW]; + f[TSE] = f_TSE + feq[TSE]; + f[TSW] = f_TSW + feq[TSW]; + f[BNE] = f_TSW + feq[BNE]; + f[BNW] = f_TSE + feq[BNW]; + f[BSE] = f_TNW + feq[BSE]; + f[BSW] = f_TNE + feq[BSW]; + f[REST] = f_ZERO + feq[REST]; + + //calcFeqsFct(f,rho,vx1,vx2,vx3); + //distributions->setDistribution(f, ix1, ix2, ix3); + distributions->setDistributionInv(f, ix1, ix2, ix3); + + //distributions->swap(); + //distributions->setDistribution(f, ix1, ix2, ix3); + //distributions->setDistributionInv(f, ix1, ix2, ix3); + //distributions->swap(); + + } + } + + //variablen der functions loeschen, da die verwiesenen Objecte nach dem verlassen des scopes ungueltig sind! + this->muVx1.ClearVar(); + this->muVx2.ClearVar(); + this->muVx3.ClearVar(); + this->muRho.ClearVar(); + +} +////////////////////////////////////////////////////////////////////////// +void InitDistributionsBlockVisitor::checkFunction(mu::Parser fct) +{ + double x1=1.0,x2=1.0,x3=1.0; + fct.DefineVar("x1",&x1); + fct.DefineVar("x2",&x2); + fct.DefineVar("x3",&x3); + + try + { + fct.Eval(); + fct.ClearVar(); + } + catch(mu::ParserError& e) + { + throw UbException(UB_EXARGS,"function: "+e.GetExpr() + (std::string)"error: "+e.GetMsg() + +(std::string)", only x1,x2,x3 are allowed as variables" ); + } +} +////////////////////////////////////////////////////////////////////////// + + + diff --git a/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.h b/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..be95e46b184cfa960a737a943b95cf6a09721453 --- /dev/null +++ b/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.h @@ -0,0 +1,101 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InitDistributionsBlockVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher, Soeren Freudiger +//======================================================================================= + +#ifndef InitDistributionsBlockVisitor_H +#define InitDistributionsBlockVisitor_H + +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" +#include "D3Q27System.h" + +#include <MuParser/include/muParser.h> + +class Grid3D; +class Block3D; + +//! \brief A class implements an initialization of the flow area. +//! \details +//! It is more flexible way to initialize flow area. +//! You can define functions to calculate macroscopic values for feq. +//! x1,x2,x3 are automatically defined via this adapter and are the real world +//! vertex coordinates. +//! +//!if function is invalid an UbException with detailed information is thrown +//! +//! Example: +//! \code +//! InitDistributionsBlockVisitor init; +//! init.setVx1("0.01*x2"); +//! init.setVx2("0.01*x2^2"); +//! \endcode + +class InitDistributionsBlockVisitor : public Block3DVisitor +{ +public: + typedef std::numeric_limits<LBMReal> D3Q27RealLim; + +public: + InitDistributionsBlockVisitor(); + ////////////////////////////////////////////////////////////////////////// + //automatic vars are: x1,x2, x3 + //ussage example: setVx1("x1*0.01+x2*0.003") + ////////////////////////////////////////////////////////////////////////// + void setVx1( const mu::Parser& parser); + void setVx2( const mu::Parser& parser); + void setVx3( const mu::Parser& parser); + void setRho( const mu::Parser& parser); + + void setVx1( const std::string& muParserString); + void setVx2( const std::string& muParserString); + void setVx3( const std::string& muParserString); + void setRho( const std::string& muParserString); + ////////////////////////////////////////////////////////////////////////// + void setVx1( LBMReal vx1 ); + void setVx2( LBMReal vx2 ); + void setVx3( LBMReal vx3 ); + void setRho( LBMReal rho ); + + void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override; + +protected: + void checkFunction(mu::Parser fct); + +private: + mu::Parser muVx1; + mu::Parser muVx2; + mu::Parser muVx3; + mu::Parser muRho; +}; + +#endif //D3Q27INITDISTRIBUTIONSPATCHVISITOR_H diff --git a/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.cpp b/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f90b778c3b238065caeea84c11c1927181d2d7a --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.cpp @@ -0,0 +1,57 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetBcBlocksBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "SetBcBlocksBlockVisitor.h" + +#include "Interactor3D.h" +#include "Grid3DSystem.h" +#include "Grid3D.h" +#include "Block3D.h" + +SetBcBlocksBlockVisitor::SetBcBlocksBlockVisitor(SPtr<Interactor3D> interactor) : + Block3DVisitor(0, Grid3DSystem::MAXLEVEL), interactor(interactor) +{ + +} + +void SetBcBlocksBlockVisitor::visit(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + if(block->getRank() == grid->getRank()) + { + if (block->isActive()) + { + interactor->setBCBlock(block); + } + } +} + diff --git a/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.h b/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..5a01f5959c092939397a5c89608a97d12c16c8e9 --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetBcBlocksBlockVisitor.h @@ -0,0 +1,60 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetBcBlocksBlockVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef SetBcBlocksBlockVisitor_h__ +#define SetBcBlocksBlockVisitor_h__ + +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" + +class Grid3D; +class Block3D; +class Interactor3D; + +//! \brief A class sets blocks with boundary condition nodes in Interactor3D object. +class SetBcBlocksBlockVisitor : public Block3DVisitor +{ +public: + SetBcBlocksBlockVisitor(SPtr<Interactor3D> interactor); + virtual ~SetBcBlocksBlockVisitor() {} + + virtual void visit(SPtr<Grid3D> grid, SPtr<Block3D> block); + +private: + SPtr<Interactor3D> interactor; +}; +#endif // SetBcBlocksBlockVisitor_h__ + + + diff --git a/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp b/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cec226de23250544396f59ec4960b64de22dc324 --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp @@ -0,0 +1,109 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetConnectorsBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "SetConnectorsBlockVisitor.h" +#include "D3Q27ETFullDirectConnector.h" +#include "Grid3DSystem.h" +#include "Communicator.h" +#include "Grid3D.h" + +SetConnectorsBlockVisitor::SetConnectorsBlockVisitor(SPtr<Communicator> comm, bool fullConnector, int dirs, LBMReal nu) : Block3DVisitor(0, Grid3DSystem::MAXLEVEL), comm(comm), fullConnector(fullConnector), dirs(dirs), nu(nu) +{ +} +////////////////////////////////////////////////////////////////////////// +SetConnectorsBlockVisitor::~SetConnectorsBlockVisitor(void) +{ +} +////////////////////////////////////////////////////////////////////////// +void SetConnectorsBlockVisitor::visit(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + if(!block) return; + + UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::visit() - start"); + UBLOG(logDEBUG5, block->toString()); + + gridRank = comm->getProcessID(); + grid->setRank(gridRank); + + setSameLevelConnectors(grid, block); + + UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::visit() - end"); +} +////////////////////////////////////////////////////////////////////////// +void SetConnectorsBlockVisitor::setSameLevelConnectors(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setSameLevelConnectors() - start"); + int blockRank = block->getRank(); + if (gridRank == blockRank && block->isActive()) + { + block->clearWeight(); + std::vector<SPtr<Block3D>> neighbors; + int ix1 = block->getX1(); + int ix2 = block->getX2(); + int ix3 = block->getX3(); + int level = block->getLevel(); + + for( int dir = 0; dir < dirs; dir++) + { + SPtr<Block3D> neighBlock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level); + + if(neighBlock) + { + int neighBlockRank = neighBlock->getRank(); + if(blockRank == neighBlockRank && neighBlock->isActive()) + { + SPtr<Block3DConnector> connector; + connector = SPtr<Block3DConnector>(new D3Q27ETFullDirectConnector( block, neighBlock, dir)); + block->setConnector(connector); + } + //else if(blockRank != neighBlockRank && neighBlock->isActive()) + //{ + // setRemoteConnectors(block, neighBlock, dir, fullConnector); + + // if(dir >=0 && dir<=5) + // { + // int weight = block->getWeight(neighBlockRank); + // weight++; + // block->setWeight(neighBlockRank, weight); + // } + //} + } + } + + // int weight = block->getNumberOfLocalConnectorsForSurfaces(); + //weight = 6 - weight; + //block->addWeightForAll(weight); + } + UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setSameLevelConnectors() - end"); +} + diff --git a/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h b/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..2a829103ccd8598fb2f1c1dddd9f19bf8644e861 --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h @@ -0,0 +1,65 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetConnectorsBlockVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef SETCONNECTORSBLOCKVISITOR_H +#define SETCONNECTORSBLOCKVISITOR_H + +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" +#include "D3Q27System.h" + +class Grid3D; +class Block3D; +class Communicator; +class InterpolationProcessor; + +//! \brief A class sets connectors between blocks. +class SetConnectorsBlockVisitor : public Block3DVisitor +{ +public: + SetConnectorsBlockVisitor(SPtr<Communicator> comm, bool fullConnector, int dirs, LBMReal nu); + virtual ~SetConnectorsBlockVisitor(); + void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override; + ////////////////////////////////////////////////////////////////////////// +protected: + void setSameLevelConnectors(SPtr<Grid3D> grid, SPtr<Block3D> block); + SPtr<Communicator> comm; + bool fullConnector; + int dirs; + int gridRank; + LBMReal nu; + SPtr<InterpolationProcessor> iProcessor; +}; + +#endif //SETCONNECTORSBLOCKVISITOR_H diff --git a/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp b/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..494e62781f38588b5aed14d06192eddb1da501bc --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp @@ -0,0 +1,107 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetKernelBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "SetKernelBlockVisitor.h" +#include "Grid3DSystem.h" +#include "LBMSystem.h" +#include "DataSet3D.h" +#include "BCProcessor.h" +#include "Grid3D.h" +#include "Block3D.h" +#include "LBMKernel.h" + +////////////////////////////////////////////////////////////////////////// +SetKernelBlockVisitor::SetKernelBlockVisitor(SPtr<LBMKernel> kernel, LBMReal nue, SetKernelBlockVisitor::Action action) : Block3DVisitor(0, Grid3DSystem::MAXLEVEL), kernel(kernel), nue(nue), action(action), dataSetFlag(true) +{ + +} +////////////////////////////////////////////////////////////////////////// +void SetKernelBlockVisitor::visit(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + if(kernel && (block->getRank() == grid->getRank())) + { + LBMReal collFactor = LBMSystem::calcCollisionFactor(nue, block->getLevel()); + kernel->setCollisionFactor(collFactor); + kernel->setIndex(block->getX1(), block->getX2(), block->getX3()); + kernel->setDeltaT(LBMSystem::getDeltaT(block->getLevel())); + kernel->setBlock(block); + UbTupleInt3 blockNX = grid->getBlockNX(); + kernel->setNX(std::array<int,3>{{val<1>(blockNX), val<2>(blockNX), val<3>(blockNX)}}); + SPtr<LBMKernel> newKernel = kernel->clone(); + + switch (action) + { + case SetKernelBlockVisitor::NewKernel: + block->setKernel(newKernel); + break; + case SetKernelBlockVisitor::ChangeKernel: + { + SPtr<DataSet3D> dataSet = block->getKernel()->getDataSet(); + if (!dataSet) + { + UB_THROW(UbException(UB_EXARGS, "It is not possible to change a DataSet in kernel! Old DataSet is not exist!")); + } + + newKernel->setDataSet(dataSet); + + SPtr<BCProcessor> bcProc = block->getKernel()->getBCProcessor(); + if (!bcProc) + { + UB_THROW(UbException(UB_EXARGS, "It is not possible to change a BCProcessor in kernel! Old BCProcessor is not exist!")); + } + newKernel->setBCProcessor(bcProc); + block->setKernel(newKernel); + } + break; + + case SetKernelBlockVisitor::ChangeKernelWithData: + { + SPtr<BCProcessor> bcProc = block->getKernel()->getBCProcessor(); + if (!bcProc) + { + UB_THROW(UbException(UB_EXARGS, "It is not possible to change a BCProcessor in kernel! Old BCProcessor is not exist!")); + } + newKernel->setBCProcessor(bcProc); + block->setKernel(newKernel); + } + break; + } + + } +} + +void SetKernelBlockVisitor::setNoDataSetFlag(bool flag) +{ + dataSetFlag = flag; +} + diff --git a/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h b/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..42778ae1a9e45c8c35e008e41431b6291ff60fb7 --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h @@ -0,0 +1,66 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetKernelBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef SetKernelBlockVisitor_h +#define SetKernelBlockVisitor_h + +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" +#include "LBMSystem.h" + +class Grid3D; +class Block3D; +class LBMKernel; + +//! \brief A class generates new LBMKernel and associates it with a block. +class SetKernelBlockVisitor : public Block3DVisitor +{ +public: + enum Action { NewKernel, ChangeKernel, ChangeKernelWithData}; + + SetKernelBlockVisitor(SPtr<LBMKernel> kernel, LBMReal nue, SetKernelBlockVisitor::Action action = SetKernelBlockVisitor::NewKernel); + virtual ~SetKernelBlockVisitor() {} + + void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override; + + void setNoDataSetFlag(bool flag); + +private: + SPtr<LBMKernel> kernel; + LBMReal nue; + Action action; + bool dataSetFlag; +}; + +#endif diff --git a/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.cpp b/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..472d53dee3356aa8930dc7191e312cac985ca20e --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.cpp @@ -0,0 +1,56 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetSolidBlocksBlockVisitor.cpp +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#include "SetSolidBlocksBlockVisitor.h" + +#include "Interactor3D.h" +#include "Grid3DSystem.h" +#include "Grid3D.h" +#include "Block3D.h" + +SetSolidBlocksBlockVisitor::SetSolidBlocksBlockVisitor(SPtr<Interactor3D> interactor) : + Block3DVisitor(0, Grid3DSystem::MAXLEVEL), interactor(interactor) +{ + +} + +void SetSolidBlocksBlockVisitor::visit(SPtr<Grid3D> grid, SPtr<Block3D> block) +{ + if (block->getRank() == grid->getRank()) + { + if (block->isActive()) + { + interactor->setSolidBlock(block); + } + } +} \ No newline at end of file diff --git a/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.h b/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..cfac49c75737001ef7f2e84c149fd8b6d3a3fb2a --- /dev/null +++ b/VirtualFluidsCore/Visitors/SetSolidBlocksBlockVisitor.h @@ -0,0 +1,58 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ \ +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SetSolidBlocksBlockVisitor.h +//! \ingroup Visitors +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef SetSolidBlocksBlockVisitor_h__ +#define SetSolidBlocksBlockVisitor_h__ + +#include <PointerDefinitions.h> + +#include "Block3DVisitor.h" + +class Grid3D; +class Block3D; +class Interactor3D; + +//! \brief A class sets blocks with solid nodes in Interactor3D object. +class SetSolidBlocksBlockVisitor : public Block3DVisitor +{ +public: + SetSolidBlocksBlockVisitor(SPtr<Interactor3D> interactor); + virtual ~SetSolidBlocksBlockVisitor() {} + + virtual void visit(SPtr<Grid3D> grid, SPtr<Block3D> block); + +private: + SPtr<Interactor3D> interactor; +} +#endif // SetSolidBlocksBlockVisitor_h__ +; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..1531494820a83fb71da2f9a8e05c0c852c30a48d --- /dev/null +++ b/readme.md @@ -0,0 +1,41 @@ +Software Requirements: +====================== + +CMake [cmake.org](https://cmake.org/): +* minimum version 3.13 + +Paraview [www.paraview.org](https://www.paraview.org/): +* any version, for example the most recent + +C++ Compiler: +* with C++11 support, for example gcc6.3 or Visual C++ 14.0 + +How to get VirtualFluidsCPU: +========================== + +Option 1: use git +1. checkout out https://git.irmb.bau.tu-bs.de/VirtualFluids/VirtualFluidsCPU.git with your credentials + +Option 2: without git +1. go to git.irmb.tu-bs.de +2. Log in with your credentials +3. click on VirtualFluids/VirtualFluidsCPU +4. click on the download symbol on the top right and download zip/tar.gz file + +How to build VirtualFluidsCPU: +============================ + +1. CMake the project +2. set the output path in Applications/LidDrivenCavity/LidDrivenCavity.cpp +3. build the project ("compile") +4. run the generated executable (usually in <build directory>/Applications/LidDrivenCavity) + +VirtualFluidsCPU results files: +=============================== + +VirtualFluidsCPU generates a set of multiple output directories in the prescribed output path. The flow fields can be found in the _mq_ directory. To view the flow fields, it is most conveniant to open the _mq_collection.pvd_ file in Paraview. The _bc_ directory contains the boundary condition information, the _geo_ directory contains information on the geometry of the flow domain and the _blocks_ directory contains the block grid. + +Documentation: +============== + +The doxygen generated documentation can be found [here](https://git.irmb.bau.tu-bs.de/doku/CPU).