LCOV - code coverage report
Current view: top level - coupling/configurations - CouetteConfiguration.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 146 45.9 %
Date: 2025-06-25 11:26:37 Functions: 1 1 100.0 %

          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           4 :     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::readDoubleMandatory(cfg.temp, subtag, "temperature");
     162           0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.equSteps, subtag, "equilibration-steps");
     163           0 :       tarch::configuration::ParseConfiguration::readIntOptional(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
     164             :     } else {
     165           0 :       std::cout << "Could not read input file " << filename
     166             :                 << ": Unknown microscopic "
     167           0 :                    "solver type!"
     168           0 :                 << std::endl;
     169           0 :       exit(EXIT_FAILURE);
     170             :     }
     171           4 :     tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.density, subtag, "density");
     172             : 
     173           4 :     subtag = node->FirstChildElement("macroscopic-solver");
     174           4 :     if (subtag == NULL) {
     175           0 :       std::cout << "Could not read input file " << filename
     176             :                 << ": Missing subtag: "
     177           0 :                    "macroscopic-solver"
     178           0 :                 << std::endl;
     179           0 :       exit(EXIT_FAILURE);
     180             :     }
     181          20 :     cfg.lbNumberProcesses = tarch::la::Vector<3, unsigned int>(1);
     182           4 :     tarch::configuration::ParseConfiguration::readStringMandatory(type, subtag, "type");
     183           4 :     if (type == "lb") {
     184           0 :       cfg.maSolverType = COUETTE_LB;
     185           0 :       tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
     186           0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     187           4 :     } else if (type == "fd") {
     188           4 :       cfg.maSolverType = COUETTE_FD;
     189           4 :       tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
     190           8 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     191             :     }
     192             : #if (BUILD_WITH_OPENFOAM)
     193             :     else if (type == "foam") {
     194             :       cfg.maSolverType = COUETTE_FOAM;
     195             :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
     196             :       tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.directory, subtag, "foam-setup-directory");
     197             :       tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.folder, subtag, "foam-setup-folder");
     198             :       tarch::configuration::ParseConfiguration::readVectorMandatory<12, unsigned int>(cfg.foam.boundariesWithMD, subtag, "boundaries-with-MD");
     199             :     }
     200             : #endif
     201           0 :     else if (type == "analytical") {
     202           0 :       cfg.maSolverType = COUETTE_ANALYTICAL;
     203           0 :       if (!(cfg.wallVelocity[1] == 0.0 && cfg.wallVelocity[2] == 0.0)) {
     204           0 :         std::cout << "analytic solver only supports flow in x-direction" << std::endl;
     205           0 :         exit(EXIT_FAILURE);
     206             :       }
     207             :     } else {
     208           0 :       std::cout << "Could not read input file " << filename
     209             :                 << ": Unknown macroscopic "
     210           0 :                    "solver type!"
     211           0 :                 << std::endl;
     212           0 :       exit(EXIT_FAILURE);
     213             :     }
     214           4 :     double vis;
     215           4 :     tarch::configuration::ParseConfiguration::readDoubleMandatory(vis, subtag, "viscosity");
     216           4 :     cfg.kinVisc = vis / cfg.density;
     217           4 :     tarch::configuration::ParseConfiguration::readIntMandatory(cfg.initAdvanceCycles, subtag, "init-advance-cycles");
     218             : 
     219           4 :     subtag = node->FirstChildElement("tws-loop");
     220           4 :     if (subtag == NULL)
     221           4 :       cfg.twsLoop = false;
     222             :     else {
     223           0 :       cfg.twsLoop = true;
     224           0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMin, subtag, "min");
     225           0 :       tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMax, subtag, "max");
     226           0 :       cfg.twsLoopStep = 1;
     227           0 :       tarch::configuration::ParseConfiguration::readIntOptional(cfg.twsLoopStep, subtag, "step");
     228             :     }
     229             : 
     230           4 :     if (cfg.miSolverType == SYNTHETIC) {
     231           0 :       if (cfg.macro2Md || cfg.totalNumberMDSimulations > 1 || cfg.lbNumberProcesses[0] != 1 || cfg.lbNumberProcesses[1] != 1 || cfg.lbNumberProcesses[2] != 1) {
     232           0 :         std::cout << "Invalid configuration: Synthetic MD runs sequentially on "
     233             :                      "rank 0 only. "
     234             :                   << "It does neither support parallel communication nor "
     235           0 :                      "multi-instance sampling"
     236           0 :                   << std::endl;
     237           0 :         exit(EXIT_FAILURE);
     238             :       }
     239             :     }
     240           4 :     if (cfg.maSolverType == COUETTE_ANALYTICAL) {
     241           0 :       if (cfg.twoWayCoupling) {
     242           0 :         std::cout << "Invalid configuration: COUETTE_ANALYTICAL does not "
     243           0 :                      "support twoWayCoupling"
     244           0 :                   << std::endl;
     245           0 :         exit(EXIT_FAILURE);
     246             :       }
     247             :     }
     248             : 
     249           8 :     return cfg;
     250           4 :   }
     251             : 
     252             : #if (BUILD_WITH_OPENFOAM)
     253             :   /** @brief holds the variables necessary for the interface to the IcoFoam
     254             :    * solver  */
     255             :   struct FoamConfig {
     256             :     /** @brief the path to the directory, where the folder with the IcoFoam
     257             :      * OpenFOAM setup files are */
     258             :     std::string directory;
     259             :     /** @brief the name of the OpenFOAM folder */
     260             :     std::string folder;
     261             :     /** @brief the cubic mesh with a cubic hole has 12 boundaries, this vector
     262             :      * tells which of them
     263             :      *         shall be coupled with the md; The order has to be the same as in
     264             :      * the blockMeshDict */
     265             :     tarch::la::Vector<12, unsigned int> boundariesWithMD;
     266             :   };
     267             : #endif
     268             : 
     269             :   /** @brief channel is always expected to have origin at (0.0,0.0,0.0) and to
     270             :    * be cubic (MD 30: 50.0, MD 60: 100.0, MD 120: 200.0) */
     271             :   double channelheight;
     272             :   /** @brief velocity of moving wall (lower boundary moves) */
     273             :   tarch::la::Vector<3, double> wallVelocity;
     274             :   /** @brief number of coupling cycles that will be done, while the wall
     275             :    * velocity is the wallInitVelocity */
     276             :   int wallInitCycles;
     277             :   /** @brief the velocity at the moving wall (z=0) while the wallInitCycles*/
     278             :   tarch::la::Vector<3, double> wallInitVelocity;
     279             :   /** @brief total number of oscillation periods of the oscillating wall
     280             :    * velocity*/
     281             :   double wallOscillations;
     282             :   /** @brief number of coupling cycles, that is continuum time steps; MD/DPD:
     283             :    * 1000 */
     284             :   int couplingCycles;
     285             :   /** @brief true if data will be send & received from the md to the continuum
     286             :    * solver */
     287             :   bool md2Macro;
     288             :   /** @brief true if data will be send & received from the continuum to the md
     289             :    * solver  */
     290             :   bool macro2Md;
     291             :   /** @brief true if the signal to noise ratio shall be evaluated */
     292             :   bool computeSNR;
     293             :   /** @brief true if from the md solver will be applied as boundary condition
     294             :    * for the continuum solver */
     295             :   bool twoWayCoupling;
     296             :   /** @brief number of coupling cycles before a filter is applied*/
     297             :   int filterInitCycles;
     298             :   /** @brief the time step interval for writing the md data to csv files  */
     299             :   int csvEveryTimestep;
     300             :   /** @brief the type of continuum solver */
     301             :   MacroSolverType maSolverType;
     302             :   /** @brief the type of md solver */
     303             :   MicroSolverType miSolverType;
     304             :   /** @brief the general density of the fluid under consideration */
     305             :   double density;
     306             :   /** @brief the kinematic viscosity of the fluid under consideration */
     307             :   double kinVisc;
     308             :   /** @brief only for LB couette solver: number of processes */
     309             :   tarch::la::Vector<3, unsigned int> lbNumberProcesses;
     310             :   /** @brief  only for LB couette solver: VTK plotting per time step */
     311             :   int plotEveryTimestep;
     312             :   /** @brief number of cycles the continuum solver is advanced before the
     313             :    * coupling is enabled */
     314             :   int initAdvanceCycles;
     315             :   /** @brief the start temperature for the fluid under consideration */
     316             :   double temp;
     317             :   /** @brief number of equilibartion time steps = number of time steps that
     318             :    * the md will run before the coupling is enabled */
     319             :   int equSteps;
     320             :   /** @brief the number of md simulation instances in a multi-instance
     321             :    * coupling, -1 = dynamic */
     322             :   int totalNumberMDSimulations;
     323             :   /** @brief the minimum number of md simulation instances in dynamic MD coupling  */
     324             :   int lowerBoundNumberMDSimulations;
     325             :   /** @brief only for dynamic MD: target absolute velocity error at start of all coupling cycles */
     326             :   double absVelErrStart;
     327             :   /** @brief only for dynamic MD: target absolute velocity error at end of all coupling cycles */
     328             :   double absVelErrEnd;
     329             :   /** @brief the sigma for the random noise in the case of synthetic md solver
     330             :    */
     331             :   double noiseSigma;
     332             :   /** @todo piet */
     333             :   bool twsLoop;
     334             :   /** @todo piet*/
     335             :   int twsLoopMin;
     336             :   /** @todo piet */
     337             :   int twsLoopMax;
     338             :   /** @todo piet */
     339             :   int twsLoopStep;
     340             : 
     341             : #if (BUILD_WITH_OPENFOAM)
     342             :   /** @brief the configurations for the OpenFoam solver */
     343             :   FoamConfig foam;
     344             : #endif
     345             : };
     346             : 
     347             : #endif

Generated by: LCOV version 1.14