LCOV - code coverage report
Current view: top level - coupling/configurations - CouetteConfiguration.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 45.0 % 149 67
Test Date: 2026-08-21 15:14:06 Functions: 100.0 % 1 1

            Line data    Source code
       1              : // Copyright (C) 2016 Technische Universitaet Muenchen
       2              : // This file is part of the Mamico project. For conditions of distribution
       3              : // and use, please see the copyright notice in Mamico's main folder, or at
       4              : // www5.in.tum.de/mamico
       5              : #ifndef _COUETTECONFIG_H_
       6              : #define _COUETTECONFIG_H_
       7              : 
       8              : #include "tarch/configuration/ParseConfiguration.h"
       9              : #include "tarch/la/Vector.h"
      10              : 
      11              : using tarch::configuration::ParseConfiguration;
      12              : 
      13              : namespace coupling {
      14              : namespace configurations {
      15              : 
      16              : struct CouetteConfig;
      17              : }
      18              : } // namespace coupling
      19              : /** Configuration parameters for Couette flow scenario
      20              :  *      @brief Configuration parameters for Couette flow scenario
      21              :  *
      22              :  *
      23              :  *      @author Niklas Wittmer
      24              :  */
      25            4 : struct coupling::configurations::CouetteConfig {
      26              : 
      27              : private:
      28              :   // CouetteConfig(){}
      29              : 
      30              : public:
      31              :   /** Defines the type of continuum solver for the coupled simulation  */
      32              :   enum MacroSolverType {
      33              :     COUETTE_ANALYTICAL = 0, ///< the analytical couette solver is used
      34              :                             ///< (coupling::solvers::CouetteSolver)
      35              :     COUETTE_LB = 1,         ///< the Lattice-Bolzmann solver is used
      36              :                             ///< (coupling::solvers::LBCouetteSolver)
      37              :     COUETTE_FD = 2,         ///< the 1d finite-difference solver is used
      38              :                             ///< (coupling::solvers::FiniteDifferenceSolver)
      39              :     COUETTE_FOAM = 3        ///< the IcoFoam solver is used (coupling::solvers::IcoFoam)
      40              :   };
      41              :   /** Defines the type of md solver for the coupled simulation  */
      42              :   enum MicroSolverType {
      43              :     SIMPLEMD = 0,  ///< the SimpleMD solver is used
      44              :     SYNTHETIC = 1, ///< the synthetic solver is used
      45              :     LS1 = 2        ///< the LS1 solver is used
      46              :   };
      47              : 
      48              :   /** @brief creates CouetteConfig if all elements exist and can be read
      49              :    *    @param filename
      50              :    */
      51            4 :   static CouetteConfig parseCouetteConfiguration(const std::string& filename) {
      52            4 :     CouetteConfig cfg;
      53              : 
      54            8 :     ParseConfiguration::XMLConfiguration xmlConfig = ParseConfiguration::XMLConfiguration::load(filename);
      55            4 :     tinyxml2::XMLElement* node = xmlConfig.root->FirstChildElement("couette-test");
      56              : 
      57            4 :     if (node == NULL) {
      58            0 :       std::cout << "Could not read input file " << filename
      59              :                 << ": missing element "
      60            0 :                    "<couette-test>"
      61            0 :                 << std::endl;
      62            0 :       exit(EXIT_FAILURE);
      63              :     }
      64              : 
      65            4 :     tinyxml2::XMLElement* n_mamico = node->NextSiblingElement();
      66            4 :     if (n_mamico == NULL) {
      67            0 :       std::cout << "Could not read input file " << filename << ": missing element <mamico>" << std::endl;
      68            0 :       exit(EXIT_FAILURE);
      69              :     }
      70            4 :     tinyxml2::XMLElement* n_md = n_mamico->NextSiblingElement();
      71            4 :     if (n_md == NULL) {
      72            0 :       std::cout << "Could not read input file " << filename
      73              :                 << ": missing element "
      74            0 :                    "<molecular-dynamics>"
      75            0 :                 << std::endl;
      76            0 :       exit(EXIT_FAILURE);
      77              :     }
      78            4 :     tinyxml2::XMLElement* n_fp = n_md->NextSiblingElement();
      79            4 :     if (n_fp == NULL) {
      80            0 :       std::cout << "Could not read input file " << filename
      81              :                 << ": missing element "
      82            0 :                    "<filter-pipeline>"
      83            0 :                 << std::endl;
      84            0 :       exit(EXIT_FAILURE);
      85              :     }
      86            4 :     tinyxml2::XMLElement* n_unexpected = n_fp->NextSiblingElement();
      87            4 :     if (n_unexpected != NULL) {
      88            0 :       std::cout << "Could not read input file " << filename << ": unknown element " << n_unexpected->Name() << std::endl;
      89            0 :       exit(EXIT_FAILURE);
      90              :     }
      91              : 
      92            4 :     tinyxml2::XMLElement* subtag = node->FirstChildElement("domain");
      93            4 :     if (subtag == NULL) {
      94            0 :       std::cout << "Could not read input file " << filename << ": Missing subtag: domain" << std::endl;
      95            0 :       exit(EXIT_FAILURE);
      96              :     }
      97            4 :     tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.channelheight, subtag, "channelheight");
      98            4 :     tarch::configuration::ParseConfiguration::readVectorMandatory<3, double>(cfg.wallVelocity, subtag, "wall-velocity");
      99            4 :     cfg.wallInitCycles = 0;
     100            4 :     tarch::configuration::ParseConfiguration::readIntOptional(cfg.wallInitCycles, subtag, "wall-init-cycles");
     101            4 :     if (cfg.wallInitCycles > 0)
     102            0 :       tarch::configuration::ParseConfiguration::readVectorMandatory<3, double>(cfg.wallInitVelocity, subtag, "wall-init-velocity");
     103            4 :     cfg.wallOscillations = 0;
     104            4 :     tarch::configuration::ParseConfiguration::readDoubleOptional(cfg.wallOscillations, subtag, "wall-oscillations");
     105              : 
     106            4 :     subtag = node->FirstChildElement("coupling");
     107            4 :     if (subtag == NULL) {
     108            0 :       std::cout << "Could not read input file couette.xml: Missing subtag: coupling" << std::endl;
     109            0 :       exit(EXIT_FAILURE);
     110              :     }
     111            4 :     tarch::configuration::ParseConfiguration::readIntMandatory(cfg.couplingCycles, subtag, "coupling-cycles");
     112            4 :     tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.twoWayCoupling, subtag, "two-way-coupling");
     113            4 :     tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.md2Macro, subtag, "send-from-md-to-macro");
     114            4 :     tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.macro2Md, subtag, "send-from-macro-to-md");
     115            4 :     tarch::configuration::ParseConfiguration::readIntMandatory(cfg.filterInitCycles, subtag, "filter-init-cycles");
     116            4 :     tarch::configuration::ParseConfiguration::readIntMandatory(cfg.csvEveryTimestep, subtag, "write-csv-every-timestep");
     117            4 :     tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.computeSNR, subtag, "compute-snr");
     118              : 
     119            4 :     subtag = node->FirstChildElement("microscopic-solver");
     120            4 :     if (subtag == NULL) {
     121            0 :       std::cout << "Could not read input file " << filename
     122              :                 << ": Missing subtag: "
     123            0 :                    "microscopic-solver"
     124            0 :                 << std::endl;
     125            0 :       exit(EXIT_FAILURE);
     126              :     }
     127            4 :     std::string type;
     128            4 :     tarch::configuration::ParseConfiguration::readStringMandatory(type, subtag, "type");
     129            4 :     if (type == "md") {
     130            4 :       cfg.miSolverType = SIMPLEMD;
     131            4 :       tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.temp, subtag, "temperature");
     132            4 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.equSteps, subtag, "equilibration-steps");
     133              : 
     134            4 :       std::string num_MD;
     135            4 :       tarch::configuration::ParseConfiguration::readStringMandatory(num_MD, subtag, "number-md-simulations");
     136            4 :       if (num_MD == "dynamic") {
     137            0 :         cfg.totalNumberMDSimulations = -1;
     138            0 :         cfg.lowerBoundNumberMDSimulations = 1;
     139            0 :         tarch::configuration::ParseConfiguration::readIntOptional(cfg.lowerBoundNumberMDSimulations, subtag, "min-number-md");
     140            0 :         tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.absVelErrStart, subtag, "error-start");
     141            0 :         tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.absVelErrEnd, subtag, "error-end");
     142              :       } else {
     143            4 :         tarch::configuration::ParseConfiguration::readIntMandatory(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
     144            4 :         if (cfg.totalNumberMDSimulations < 1) {
     145            0 :           std::cout << "Could not read input file " << filename
     146              :                     << ": "
     147            0 :                        "number-md-simulations < 1"
     148            0 :                     << std::endl;
     149            0 :           exit(EXIT_FAILURE);
     150              :         }
     151              :       }
     152            4 :     } else if (type == "synthetic") {
     153            0 :       cfg.miSolverType = SYNTHETIC;
     154            0 :       tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.noiseSigma, subtag, "noise-sigma");
     155            0 :       cfg.totalNumberMDSimulations = 1;
     156            0 :       tarch::configuration::ParseConfiguration::readIntOptional(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
     157            0 :     } else if (type == "ls1") {
     158            0 :       cfg.miSolverType = LS1;
     159              : 
     160            0 :       cfg.totalNumberMDSimulations = 1;
     161            0 :       tarch::configuration::ParseConfiguration::readStringOptional(cfg.ls1config, subtag, "ls1config");
     162            0 :       tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.temp, subtag, "temperature");
     163            0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.equSteps, subtag, "equilibration-steps");
     164            0 :       tarch::configuration::ParseConfiguration::readIntOptional(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
     165              :     } else {
     166            0 :       std::cout << "Could not read input file " << filename
     167              :                 << ": Unknown microscopic "
     168            0 :                    "solver type!"
     169            0 :                 << std::endl;
     170            0 :       exit(EXIT_FAILURE);
     171              :     }
     172            4 :     tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.density, subtag, "density");
     173              : 
     174            4 :     subtag = node->FirstChildElement("macroscopic-solver");
     175            4 :     if (subtag == NULL) {
     176            0 :       std::cout << "Could not read input file " << filename
     177              :                 << ": Missing subtag: "
     178            0 :                    "macroscopic-solver"
     179            0 :                 << std::endl;
     180            0 :       exit(EXIT_FAILURE);
     181              :     }
     182           20 :     cfg.lbNumberProcesses = tarch::la::Vector<3, unsigned int>(1);
     183            4 :     tarch::configuration::ParseConfiguration::readStringMandatory(type, subtag, "type");
     184            4 :     if (type == "lb") {
     185            0 :       cfg.maSolverType = COUETTE_LB;
     186            0 :       tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
     187            0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     188            0 :       cfg.plotAverageVelocity = false;
     189            0 :       tarch::configuration::ParseConfiguration::readBoolOptional(cfg.plotAverageVelocity, subtag, "plot-average-velocity");
     190            4 :     } else if (type == "fd") {
     191            4 :       cfg.maSolverType = COUETTE_FD;
     192            4 :       tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
     193            8 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     194              :     }
     195              : #if (BUILD_WITH_OPENFOAM)
     196              :     else if (type == "foam") {
     197              :       cfg.maSolverType = COUETTE_FOAM;
     198              :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     199              :       tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.directory, subtag, "foam-setup-directory");
     200              :       tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.folder, subtag, "foam-setup-folder");
     201              :       tarch::configuration::ParseConfiguration::readVectorMandatory<12, unsigned int>(cfg.foam.boundariesWithMD, subtag, "boundaries-with-MD");
     202              :     }
     203              : #endif
     204            0 :     else if (type == "analytical") {
     205            0 :       cfg.maSolverType = COUETTE_ANALYTICAL;
     206            0 :       if (!(cfg.wallVelocity[1] == 0.0 && cfg.wallVelocity[2] == 0.0)) {
     207            0 :         std::cout << "analytic solver only supports flow in x-direction" << std::endl;
     208            0 :         exit(EXIT_FAILURE);
     209              :       }
     210              :     } else {
     211            0 :       std::cout << "Could not read input file " << filename
     212              :                 << ": Unknown macroscopic "
     213            0 :                    "solver type!"
     214            0 :                 << std::endl;
     215            0 :       exit(EXIT_FAILURE);
     216              :     }
     217            4 :     double vis;
     218            4 :     tarch::configuration::ParseConfiguration::readDoubleMandatory(vis, subtag, "viscosity");
     219            4 :     cfg.kinVisc = vis / cfg.density;
     220            4 :     tarch::configuration::ParseConfiguration::readIntMandatory(cfg.initAdvanceCycles, subtag, "init-advance-cycles");
     221              : 
     222            4 :     subtag = node->FirstChildElement("tws-loop");
     223            4 :     if (subtag == NULL)
     224            4 :       cfg.twsLoop = false;
     225              :     else {
     226            0 :       cfg.twsLoop = true;
     227            0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMin, subtag, "min");
     228            0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMax, subtag, "max");
     229            0 :       cfg.twsLoopStep = 1;
     230            0 :       tarch::configuration::ParseConfiguration::readIntOptional(cfg.twsLoopStep, subtag, "step");
     231              :     }
     232              : 
     233            4 :     if (cfg.miSolverType == SYNTHETIC) {
     234            0 :       if (cfg.macro2Md || cfg.totalNumberMDSimulations > 1 || cfg.lbNumberProcesses[0] != 1 || cfg.lbNumberProcesses[1] != 1 || cfg.lbNumberProcesses[2] != 1) {
     235            0 :         std::cout << "Invalid configuration: Synthetic MD runs sequentially on "
     236              :                      "rank 0 only. "
     237              :                   << "It does neither support parallel communication nor "
     238            0 :                      "multi-instance sampling"
     239            0 :                   << std::endl;
     240            0 :         exit(EXIT_FAILURE);
     241              :       }
     242              :     }
     243            4 :     if (cfg.maSolverType == COUETTE_ANALYTICAL) {
     244            0 :       if (cfg.twoWayCoupling) {
     245            0 :         std::cout << "Invalid configuration: COUETTE_ANALYTICAL does not "
     246            0 :                      "support twoWayCoupling"
     247            0 :                   << std::endl;
     248            0 :         exit(EXIT_FAILURE);
     249              :       }
     250              :     }
     251              : 
     252            8 :     return cfg;
     253            4 :   }
     254              : 
     255              : #if (BUILD_WITH_OPENFOAM)
     256              :   /** @brief holds the variables necessary for the interface to the IcoFoam
     257              :    * solver  */
     258              :   struct FoamConfig {
     259              :     /** @brief the path to the directory, where the folder with the IcoFoam
     260              :      * OpenFOAM setup files are */
     261              :     std::string directory;
     262              :     /** @brief the name of the OpenFOAM folder */
     263              :     std::string folder;
     264              :     /** @brief the cubic mesh with a cubic hole has 12 boundaries, this vector
     265              :      * tells which of them
     266              :      *         shall be coupled with the md; The order has to be the same as in
     267              :      * the blockMeshDict */
     268              :     tarch::la::Vector<12, unsigned int> boundariesWithMD;
     269              :   };
     270              : #endif
     271              : 
     272              :   /** @brief channel is always expected to have origin at (0.0,0.0,0.0) and to
     273              :    * be cubic (MD 30: 50.0, MD 60: 100.0, MD 120: 200.0) */
     274              :   double channelheight;
     275              :   /** @brief velocity of moving wall (lower boundary moves) */
     276              :   tarch::la::Vector<3, double> wallVelocity;
     277              :   /** @brief number of coupling cycles that will be done, while the wall
     278              :    * velocity is the wallInitVelocity */
     279              :   int wallInitCycles;
     280              :   /** @brief the velocity at the moving wall (z=0) while the wallInitCycles*/
     281              :   tarch::la::Vector<3, double> wallInitVelocity;
     282              :   /** @brief total number of oscillation periods of the oscillating wall
     283              :    * velocity*/
     284              :   double wallOscillations;
     285              :   /** @brief number of coupling cycles, that is continuum time steps; MD/DPD:
     286              :    * 1000 */
     287              :   int couplingCycles;
     288              :   /** @brief true if data will be send & received from the md to the continuum
     289              :    * solver */
     290              :   bool md2Macro;
     291              :   /** @brief true if data will be send & received from the continuum to the md
     292              :    * solver  */
     293              :   bool macro2Md;
     294              :   /** @brief true if the signal to noise ratio shall be evaluated */
     295              :   bool computeSNR;
     296              :   /** @brief true if from the md solver will be applied as boundary condition
     297              :    * for the continuum solver */
     298              :   bool twoWayCoupling;
     299              :   /** @brief number of coupling cycles before a filter is applied*/
     300              :   int filterInitCycles;
     301              :   /** @brief the time step interval for writing the md data to csv files  */
     302              :   int csvEveryTimestep;
     303              :   /** @brief the type of continuum solver */
     304              :   MacroSolverType maSolverType;
     305              :   /** @brief the type of md solver */
     306              :   MicroSolverType miSolverType;
     307              :   /** @brief the general density of the fluid under consideration */
     308              :   double density;
     309              :   /** @brief the kinematic viscosity of the fluid under consideration */
     310              :   double kinVisc;
     311              :   /** @brief only for LB couette solver: number of processes */
     312              :   tarch::la::Vector<3, unsigned int> lbNumberProcesses;
     313              :   /** @brief  only for LB couette solver: VTK plotting per time step */
     314              :   int plotEveryTimestep;
     315              :   /** @brief  only for LB couette solver: CSV plotting of average velocity */
     316              :   bool plotAverageVelocity;
     317              :   /** @brief number of cycles the continuum solver is advanced before the
     318              :    * coupling is enabled */
     319              :   int initAdvanceCycles;
     320              :   /** @brief the start temperature for the fluid under consideration */
     321              :   double temp;
     322              :   /** @brief number of equilibartion time steps = number of time steps that
     323              :    * the md will run before the coupling is enabled */
     324              :   int equSteps;
     325              :   /** @brief the number of md simulation instances in a multi-instance
     326              :    * coupling, -1 = dynamic */
     327              :   int totalNumberMDSimulations;
     328              :   /** @brief the minimum number of md simulation instances in dynamic MD coupling  */
     329              :   int lowerBoundNumberMDSimulations;
     330              :   /** @brief only for dynamic MD: target absolute velocity error at start of all coupling cycles */
     331              :   double absVelErrStart;
     332              :   /** @brief only for dynamic MD: target absolute velocity error at end of all coupling cycles */
     333              :   double absVelErrEnd;
     334              :   /** @brief the sigma for the random noise in the case of synthetic md solver
     335              :    */
     336              :   double noiseSigma;
     337              :   /** @todo piet */
     338              :   bool twsLoop;
     339              :   /** @todo piet*/
     340              :   int twsLoopMin;
     341              :   /** @todo piet */
     342              :   int twsLoopMax;
     343              :   /** @todo piet */
     344              :   int twsLoopStep;
     345              :   /* @brief ls1 configuration filename (only relevant when using ls1 as MD solver)*/
     346              :   std::string ls1config = "ls1config.xml";
     347              : 
     348              : #if (BUILD_WITH_OPENFOAM)
     349              :   /** @brief the configurations for the OpenFoam solver */
     350              :   FoamConfig foam;
     351              : #endif
     352              : };
     353              : 
     354              : #endif
        

Generated by: LCOV version 2.0-1