LCOV - code coverage report
Current view: top level - src/mesh - RinglebMesh.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 114 119 95.8 %
Date: 2025-07-17 01:28:37 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "RinglebMesh.h"
      11             : 
      12             : #include "MooseApp.h"
      13             : 
      14             : #include "libmesh/face_quad4.h"
      15             : #include "libmesh/face_tri3.h"
      16             : #include "libmesh/mesh_modification.h"
      17             : 
      18             : registerMooseObject("MooseApp", RinglebMesh);
      19             : 
      20             : InputParameters
      21       14285 : RinglebMesh::validParams()
      22             : {
      23       14285 :   InputParameters params = MooseMesh::validParams();
      24       14285 :   params.addRequiredParam<Real>("gamma", "Gamma parameter");
      25       14285 :   params.addRequiredParam<Real>("kmax", "Value of k on the inner wall.");
      26       14285 :   params.addRequiredParam<Real>("kmin", "Value of k on the outer wall.");
      27       14285 :   params.addRequiredParam<int>("num_q_pts",
      28             :                                "How many points to discretize the range q = (0.5, k) into.");
      29       14285 :   params.addRequiredParam<int>("n_extra_q_pts",
      30             :                                "How many 'extra' points should be inserted in the final element"
      31             :                                " *in addition to* the equispaced q points.");
      32       14285 :   params.addRequiredParam<int>("num_k_pts", "How many points in the range k=(kmin, kmax).");
      33       14285 :   params.addParam<boundary_id_type>("inflow_bid", 1, "The boundary id to use for the inflow");
      34       42855 :   params.addParam<boundary_id_type>(
      35       28570 :       "inner_wall_bid", 2, "The boundary id to use for the inner wall");
      36       14285 :   params.addParam<boundary_id_type>("outflow_bid", 3, "The boundary id to use for the outflow");
      37       42855 :   params.addParam<boundary_id_type>(
      38       28570 :       "outer_wall_bid", 4, "The boundary id to use for the outer wall");
      39       42855 :   params.addParam<bool>(
      40       28570 :       "triangles", false, "If true, all the quadrilateral elements will be split into triangles");
      41       14285 :   params.addClassDescription("Creates a mesh for the Ringleb problem.");
      42             : 
      43       14285 :   return params;
      44           0 : }
      45             : 
      46          10 : RinglebMesh::RinglebMesh(const InputParameters & parameters)
      47             :   : MooseMesh(parameters),
      48          10 :     _gamma(getParam<Real>("gamma")),
      49          10 :     _kmax(getParam<Real>("kmax")),
      50          10 :     _kmin(getParam<Real>("kmin")),
      51          10 :     _num_q_pts(getParam<int>("num_q_pts")),
      52          10 :     _n_extra_q_pts(getParam<int>("n_extra_q_pts")),
      53          10 :     _num_k_pts(getParam<int>("num_k_pts")),
      54          10 :     _inflow_bid(getParam<boundary_id_type>("inflow_bid")),
      55          10 :     _outflow_bid(getParam<boundary_id_type>("outflow_bid")),
      56          10 :     _inner_wall_bid(getParam<boundary_id_type>("inner_wall_bid")),
      57          10 :     _outer_wall_bid(getParam<boundary_id_type>("outer_wall_bid")),
      58          20 :     _triangles(getParam<bool>("triangles"))
      59             : {
      60             : 
      61             :   // catch likely user errors
      62          10 :   if (_kmax <= _kmin)
      63           0 :     mooseError("RinglebMesh: kmax must be greater than kmin");
      64          10 : }
      65             : 
      66             : std::unique_ptr<MooseMesh>
      67           0 : RinglebMesh::safeClone() const
      68             : {
      69           0 :   return _app.getFactory().copyConstruct(*this);
      70             : }
      71             : 
      72             : std::vector<Real>
      73        3960 : RinglebMesh::arhopj(const Real & gamma, const std::vector<Real> & q, const int & index)
      74             : {
      75        3960 :   std::vector<Real> values(4);
      76        3960 :   Real a = std::sqrt(1 - ((gamma - 1) / 2.) * std::pow(q[index], 2));
      77        3960 :   Real rho = std::pow(a, 2. / (gamma - 1));
      78        3960 :   Real p = (1. / gamma) * std::pow(a, 2 * gamma / (gamma - 1));
      79        3960 :   Real J = 1. / a + 1. / (3. * std::pow(a, 3)) + 1. / (5. * std::pow(a, 5)) -
      80        3960 :            0.5 * std::log((1 + a) / (1 - a));
      81        3960 :   values = {a, rho, p, J};
      82        3960 :   return values;
      83           0 : }
      84             : 
      85             : std::vector<Real>
      86        3960 : RinglebMesh::computexy(const std::vector<Real> values,
      87             :                        const int & i,
      88             :                        const int & index,
      89             :                        const std::vector<Real> & ks,
      90             :                        const std::vector<Real> & q)
      91             : {
      92        3960 :   std::vector<Real> xy(2);
      93             : 
      94             :   // Compute x(q,k)
      95        3960 :   xy[0] = 0.5 / values[1] * (2. / ks[i] / ks[i] - 1. / q[index] / q[index]) - 0.5 * values[3];
      96             : 
      97             :   // Compute the term that goes under the sqrt sign
      98             :   // If 1 - (q/k)^2 is slightly negative, we make it zero.
      99        3960 :   Real sqrt_term = 1. - q[index] * q[index] / ks[i] / ks[i];
     100        3960 :   sqrt_term = std::max(sqrt_term, 0.);
     101             : 
     102             :   // Compute y(q,k)
     103        3960 :   xy[1] = 1. / (ks[i] * values[1] * q[index]) * std::sqrt(sqrt_term);
     104             : 
     105        7920 :   return xy;
     106             : }
     107             : 
     108             : void
     109          10 : RinglebMesh::buildMesh()
     110             : {
     111          10 :   MeshBase & mesh = getMesh();
     112          10 :   BoundaryInfo & boundary_info = mesh.get_boundary_info();
     113             : 
     114             :   /// Data structure that holds pointers to the Nodes of each streamline.
     115          10 :   std::vector<std::vector<Node *>> stream_nodes(_num_k_pts);
     116             : 
     117             :   /// Node id counter.
     118          10 :   int current_node_id = 0;
     119             : 
     120             :   /// Vector containing the regularly spaced k values
     121          10 :   std::vector<Real> ks(_num_k_pts);
     122          10 :   Real diff = (_kmax - _kmin) / (_num_k_pts - 1);
     123         100 :   for (int i = 0; i < _num_k_pts; i++)
     124          90 :     ks[i] = _kmin + i * diff;
     125             : 
     126         100 :   for (int i = 0; i < _num_k_pts; i++)
     127             :   {
     128          90 :     stream_nodes[i].resize(2 * (_num_q_pts + _n_extra_q_pts));
     129             : 
     130             :     /// Vector containing the regularly spaced (and the extra q points) q values
     131          90 :     std::vector<Real> q(_num_q_pts);
     132          90 :     Real diffq = (ks[i] - 0.5) / (_num_q_pts - 1);
     133        1890 :     for (int j = 0; j < _num_q_pts; j++)
     134        1800 :       q[j] = 0.5 + j * diffq;
     135             : 
     136             :     /// Add the extra q points
     137         270 :     for (int j = _num_q_pts; j < _num_q_pts + _n_extra_q_pts; j++)
     138             :     {
     139         180 :       std::vector<Real>::iterator it = q.end();
     140         180 :       q.insert(--it, 0.3 * q[j - 2] + 0.7 * q[j - 1]);
     141             :     }
     142             : 
     143          90 :     std::vector<Real> vals(4);
     144          90 :     std::vector<Real> xy(2);
     145             :     /// Create the nodes for the upper part
     146        2070 :     for (int j = 0; j < _num_q_pts + _n_extra_q_pts; j++)
     147             :     {
     148             :       // Compute the different parameters
     149        1980 :       vals = arhopj(_gamma, q, j);
     150             : 
     151             :       // Compute x and y
     152        1980 :       xy = computexy(vals, i, j, ks, q);
     153             : 
     154             :       // Create a node with (x,y) coordinates as it's on the upper part of the mesh
     155        1980 :       if (j != _num_q_pts + _n_extra_q_pts - 1)
     156        1890 :         stream_nodes[i][j] = mesh.add_point(Point(xy[0], xy[1]), current_node_id++);
     157             :     }
     158             : 
     159             :     /// Create the nodes for the lower part
     160        2070 :     for (int j = _num_q_pts + _n_extra_q_pts; j < 2 * (_num_q_pts + _n_extra_q_pts); j++)
     161             :     {
     162        1980 :       int index = 2 * (_num_q_pts + _n_extra_q_pts) - 1 - j;
     163             :       // Compute the different parameters
     164        1980 :       vals = arhopj(_gamma, q, index);
     165             : 
     166             :       // Compute x and y
     167        1980 :       xy = computexy(vals, i, index, ks, q);
     168             : 
     169             :       // Create a node with (x,-y) coordinates as it's on the lower part of the mesh
     170        1980 :       stream_nodes[i][j] = mesh.add_point(Point(xy[0], -xy[1]), current_node_id++);
     171             :     }
     172          90 :   }
     173             : 
     174             :   /// Add elements for the whole mesh
     175          90 :   for (int i = 0; i < _num_k_pts - 1; i++)
     176             :   {
     177        3520 :     for (int j = 0; j < 2 * (_num_q_pts + _n_extra_q_pts) - 1; j++)
     178             :     {
     179             :       /// This is done in order to avoid having two nodes at the exact same location (on the straight       /// line y=0)
     180        3440 :       if (j != _num_q_pts + _n_extra_q_pts - 1 and j != _num_q_pts + _n_extra_q_pts - 2)
     181             :       {
     182        3280 :         Elem * elem = mesh.add_elem(new Quad4);
     183        3280 :         elem->set_node(0, stream_nodes[i][j]);
     184        3280 :         elem->set_node(1, stream_nodes[i][j + 1]);
     185        3280 :         elem->set_node(2, stream_nodes[i + 1][j + 1]);
     186        3280 :         elem->set_node(3, stream_nodes[i + 1][j]);
     187             : 
     188        3280 :         if (i == 0)
     189         410 :           boundary_info.add_side(elem->id(), /*side=*/0, _outer_wall_bid);
     190        3280 :         if (j == 0)
     191          80 :           boundary_info.add_side(elem->id(), /*side=*/3, _inflow_bid);
     192        3280 :         if (j == 2 * (_num_q_pts + _n_extra_q_pts) - 2)
     193          80 :           boundary_info.add_side(elem->id(), /*side=*/1, _outflow_bid);
     194        3280 :         if (i == _num_k_pts - 2)
     195         410 :           boundary_info.add_side(elem->id(), /*side=*/2, _inner_wall_bid);
     196        3280 :       }
     197         160 :       else if (j == _num_q_pts + _n_extra_q_pts - 2)
     198             :       {
     199          80 :         Elem * elem = mesh.add_elem(new Quad4);
     200          80 :         elem->set_node(0, stream_nodes[i][j]);
     201          80 :         elem->set_node(1, stream_nodes[i][j + 2]);
     202          80 :         elem->set_node(2, stream_nodes[i + 1][j + 2]);
     203          80 :         elem->set_node(3, stream_nodes[i + 1][j]);
     204             : 
     205          80 :         if (i == 0)
     206          10 :           boundary_info.add_side(elem->id(), /*side=*/0, _outer_wall_bid);
     207          80 :         if (i == _num_k_pts - 2)
     208          10 :           boundary_info.add_side(elem->id(), /*side=*/2, _inner_wall_bid);
     209             :       }
     210             :     }
     211             :   }
     212             : 
     213             :   /// Find neighbors, etc.
     214          10 :   mesh.prepare_for_use();
     215             : 
     216             :   /// Create the triangular elements if required by the user
     217          10 :   if (_triangles)
     218          10 :     MeshTools::Modification::all_tri(mesh);
     219             : 
     220             :   /// Create sideset names.
     221          10 :   boundary_info.sideset_name(_inflow_bid) = "inflow";
     222          10 :   boundary_info.sideset_name(_outflow_bid) = "outflow";
     223          10 :   boundary_info.sideset_name(_inner_wall_bid) = "inner_wall";
     224          10 :   boundary_info.sideset_name(_outer_wall_bid) = "outer_wall";
     225          10 : }

Generated by: LCOV version 1.14