LCOV - code coverage report
Current view: top level - src/userobjects - EBSDReader.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 211 267 79.0 %
Date: 2025-09-04 07:55:36 Functions: 20 20 100.0 %
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 "EBSDReader.h"
      11             : #include "EBSDMesh.h"
      12             : #include "MooseMesh.h"
      13             : #include "Conversion.h"
      14             : #include "NonlinearSystem.h"
      15             : 
      16             : #include "libmesh/int_range.h"
      17             : 
      18             : #include <Eigen/Dense>
      19             : 
      20             : #include <fstream>
      21             : 
      22             : registerMooseObject("PhaseFieldApp", EBSDReader);
      23             : 
      24             : InputParameters
      25         336 : EBSDReader::validParams()
      26             : {
      27         336 :   InputParameters params = EulerAngleProvider::validParams();
      28         336 :   params.addClassDescription("Load and manage DREAM.3D EBSD data files for running simulations on "
      29             :                              "reconstructed microstructures.");
      30         672 :   params.addParam<unsigned int>(
      31         672 :       "custom_columns", 0, "Number of additional custom data columns to read from the EBSD file");
      32         672 :   params.addParam<unsigned int>("bins", 20, "Number of bins to segregate quaternions");
      33         672 :   params.addParam<Real>("L_norm", 1, "Specifies the type of average the user intends to perform");
      34         672 :   params.addParam<std::string>("ebsd_meshgenerator",
      35             :                                "Specify the name of the EBSDMeshGenerator. The EBSDReader can "
      36             :                                "autodetect this, if only one such MeshGenerator exists.");
      37         336 :   return params;
      38           0 : }
      39             : 
      40         168 : EBSDReader::EBSDReader(const InputParameters & params)
      41             :   : EulerAngleProvider(params),
      42         336 :     _mesh(_fe_problem.mesh()),
      43         168 :     _nl(_fe_problem.getNonlinearSystemBase(_sys.number())),
      44         168 :     _grain_num(0),
      45         336 :     _custom_columns(getParam<unsigned int>("custom_columns")),
      46         168 :     _time_step(_fe_problem.timeStep()),
      47         168 :     _mesh_dimension(_mesh.dimension()),
      48         336 :     _bins(getParam<unsigned int>("bins")),
      49         336 :     _L_norm(getParam<Real>("L_norm")),
      50         168 :     _nx(0),
      51         168 :     _ny(0),
      52         168 :     _nz(0),
      53         168 :     _dx(0.),
      54         168 :     _dy(0.),
      55         168 :     _dz(0.)
      56             : {
      57         168 :   readFile();
      58             :   // throws an error for zero bins
      59         168 :   if (_bins == 0)
      60           0 :     mooseError("One cannot have zero bins");
      61         168 : }
      62             : 
      63             : void
      64         168 : EBSDReader::readFile()
      65             : {
      66             :   std::string ebsd_filename;
      67             :   EBSDMeshGenerator::Geometry geometry;
      68             : 
      69             :   // Fetch and check mesh or meshgenerators
      70         168 :   EBSDMesh * mesh = dynamic_cast<EBSDMesh *>(&_mesh);
      71         168 :   if (mesh != NULL)
      72             :   {
      73             :     ebsd_filename = mesh->getEBSDFilename();
      74           0 :     geometry = mesh->getEBSDGeometry();
      75             :   }
      76             :   else
      77             :   {
      78             :     std::string ebsd_meshgenerator_name;
      79         336 :     if (isParamValid("ebsd_meshgenerator"))
      80           0 :       ebsd_meshgenerator_name = getParam<std::string>("ebsd_meshgenerator");
      81             :     else
      82             :     {
      83         168 :       auto meshgenerator_names = _app.getMeshGeneratorNames();
      84         504 :       for (auto & mgn : meshgenerator_names)
      85             :       {
      86             :         const EBSDMeshGenerator * emg =
      87         336 :             dynamic_cast<const EBSDMeshGenerator *>(&_app.getMeshGenerator(mgn));
      88         336 :         if (emg)
      89             :         {
      90         168 :           if (!ebsd_meshgenerator_name.empty())
      91           0 :             mooseError("Found multiple EBSDMeshGenerator objects (",
      92             :                        ebsd_meshgenerator_name,
      93             :                        " and ",
      94             :                        mgn,
      95             :                        "). Use the 'ebsd_meshgenerator' parameter to specify which one to use.");
      96             :           ebsd_meshgenerator_name = mgn;
      97             :         }
      98             :       }
      99             : 
     100         168 :       if (ebsd_meshgenerator_name.empty())
     101           0 :         mooseError("Failed to autodetect an EBSDMeshGenerator (or a deprecated EBSDMesh object).");
     102         168 :     }
     103             : 
     104             :     // get the selected or detected mesh generator
     105             :     const EBSDMeshGenerator * emg =
     106         168 :         dynamic_cast<const EBSDMeshGenerator *>(&_app.getMeshGenerator(ebsd_meshgenerator_name));
     107         168 :     if (!emg)
     108           0 :       paramError("ebsd_meshgenerator", "No valid EBSDMeshGenerator object found.");
     109             : 
     110             :     ebsd_filename = emg->getEBSDFilename();
     111         168 :     geometry = emg->getEBSDGeometry();
     112             :   }
     113             : 
     114         168 :   std::ifstream stream_in(ebsd_filename.c_str());
     115         168 :   if (!stream_in)
     116           0 :     mooseError("Can't open EBSD file: ", ebsd_filename);
     117             : 
     118             :   // Copy file header data from the EBSDMesh
     119         168 :   _dx = geometry.d[0];
     120         168 :   _nx = geometry.n[0];
     121         168 :   _minx = geometry.min[0];
     122         168 :   _maxx = _minx + _dx * _nx;
     123             : 
     124         168 :   _dy = geometry.d[1];
     125         168 :   _ny = geometry.n[1];
     126         168 :   _miny = geometry.min[1];
     127         168 :   _maxy = _miny + _dy * _ny;
     128             : 
     129         168 :   _dz = geometry.d[2];
     130         168 :   _nz = geometry.n[2];
     131         168 :   _minz = geometry.min[2];
     132         168 :   _maxz = _minz + _dz * _nz;
     133             : 
     134             :   // Resize the _data array
     135         168 :   unsigned total_size = geometry.dim < 3 ? _nx * _ny : _nx * _ny * _nz;
     136         168 :   _data.resize(total_size);
     137             : 
     138             :   std::string line;
     139      299320 :   while (std::getline(stream_in, line))
     140             :   {
     141      299152 :     if (line.find("#") != 0)
     142             :     {
     143             :       // Temporary variables to read in on each line
     144             :       EBSDPointData d;
     145             :       Real x, y, z;
     146             : 
     147      293306 :       std::istringstream iss(line);
     148             :       iss >> d._phi1 >> d._Phi >> d._phi2 >> x >> y >> z >> d._feature_id >> d._phase >>
     149             :           d._symmetry;
     150             : 
     151             :       // Transform angles to degrees
     152      293306 :       d._phi1 *= 180.0 / libMesh::pi;
     153      293306 :       d._Phi *= 180.0 / libMesh::pi;
     154      293306 :       d._phi2 *= 180.0 / libMesh::pi;
     155             : 
     156             :       // Custom columns
     157      293306 :       d._custom.resize(_custom_columns);
     158      293306 :       for (unsigned int i = 0; i < _custom_columns; ++i)
     159           0 :         if (!(iss >> d._custom[i]))
     160           0 :           mooseError("Unable to read in EBSD custom data column #", i);
     161             : 
     162      293306 :       if (x < _minx || y < _miny || x > _maxx || y > _maxy ||
     163           0 :           (geometry.dim == 3 && (z < _minz || z > _maxz)))
     164           0 :         mooseError("EBSD Data ouside of the domain declared in the header ([",
     165           0 :                    _minx,
     166           0 :                    ':',
     167           0 :                    _maxx,
     168             :                    "], [",
     169           0 :                    _miny,
     170           0 :                    ':',
     171           0 :                    _maxy,
     172             :                    "], [",
     173           0 :                    _minz,
     174           0 :                    ':',
     175           0 :                    _maxz,
     176             :                    "]) dim=",
     177             :                    geometry.dim,
     178             :                    "\n",
     179             :                    line);
     180             : 
     181      293306 :       d._p = Point(x, y, z);
     182             : 
     183             :       // determine number of grains in the dataset
     184      293306 :       if (_global_id_map.find(d._feature_id) == _global_id_map.end())
     185        3546 :         _global_id_map[d._feature_id] = _grain_num++;
     186             : 
     187      293306 :       unsigned int global_index = indexFromPoint(Point(x, y, z));
     188      293306 :       _data[global_index] = d;
     189      293306 :     }
     190             :   }
     191         168 :   stream_in.close();
     192             : 
     193             :   // Resize the variables
     194         168 :   _avg_data.resize(_grain_num);
     195         168 :   _avg_angles.resize(_grain_num);
     196             : 
     197             :   // clear the averages
     198        3714 :   for (const auto i : make_range(_grain_num))
     199             :   {
     200        3546 :     EBSDAvgData & a = _avg_data[i];
     201        3546 :     a._symmetry = a._phase = a._n = 0;
     202        3546 :     a._p = 0.0;
     203        3546 :     a._custom.assign(_custom_columns, 0.0);
     204             : 
     205             :     EulerAngles & b = _avg_angles[i];
     206        3546 :     b.phi1 = b.Phi = b.phi2 = 0.0;
     207             :   }
     208             : 
     209             :   // Array of vectors to store quaternions of each grain
     210         168 :   std::vector<std::vector<Eigen::Quaternion<Real>>> quat(_grain_num);
     211             : 
     212             :   // Iterate through data points to store orientation information for each grain
     213      293474 :   for (auto & j : _data)
     214             :   {
     215      293306 :     EBSDAvgData & a = _avg_data[_global_id_map[j._feature_id]];
     216      293306 :     EulerAngles angles;
     217             : 
     218      293306 :     angles.phi1 = j._phi1;
     219      293306 :     angles.Phi = j._Phi;
     220      293306 :     angles.phi2 = j._phi2;
     221             : 
     222             :     // convert Euler angles to quaternions
     223      293306 :     Eigen::Quaternion<Real> q = angles.toQuaternion();
     224      293306 :     quat[_global_id_map[j._feature_id]].push_back(q);
     225             : 
     226      293306 :     if (a._n == 0)
     227        3546 :       a._phase = j._phase;
     228      289760 :     else if (a._phase != j._phase)
     229           0 :       mooseError("An EBSD feature needs to have a uniform phase.");
     230             : 
     231      293306 :     if (a._n == 0)
     232        3546 :       a._symmetry = j._symmetry;
     233      289760 :     else if (a._symmetry != j._symmetry)
     234           0 :       mooseError("An EBSD feature needs to have a uniform symmetry parameter.");
     235             : 
     236      293306 :     for (unsigned int i = 0; i < _custom_columns; ++i)
     237           0 :       a._custom[i] += j._custom[i];
     238             : 
     239             :     // store the feature (or grain) ID
     240      293306 :     a._feature_id = j._feature_id;
     241             : 
     242             :     a._p += j._p;
     243      293306 :     a._n++;
     244             :   }
     245             : 
     246        3714 :   for (const auto i : make_range(_grain_num))
     247             :   {
     248        3546 :     EBSDAvgData & a = _avg_data[i];
     249             :     EulerAngles & b = _avg_angles[i];
     250             : 
     251        3546 :     if (a._n == 0)
     252           0 :       continue;
     253             : 
     254             :     // creating a map to store the quaternion count for each bin index
     255             :     std::map<std::tuple<int, int, int, int>, unsigned int> feature_weights;
     256             : 
     257             :     // looping through all quaternions of the current grain
     258      296852 :     for (const auto & q : quat[i])
     259             :     {
     260      293306 :       const auto bin = std::make_tuple<int, int, int, int>(std::floor(q.w() * 0.5 * _bins),
     261      293306 :                                                            std::floor(q.x() * 0.5 * _bins),
     262      293306 :                                                            std::floor(q.y() * 0.5 * _bins),
     263      293306 :                                                            std::floor(q.z() * 0.5 * _bins));
     264      293306 :       feature_weights[bin]++;
     265             :     }
     266             : 
     267             :     /**
     268             :      * Markley, F. Landis, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman.
     269             :      * "Averaging quaternions." Journal of Guidance, Control, and Dynamics 30,
     270             :      * no. 4 (2007): 1193-1197.
     271             :      * A 4 by N matrix (Q) is constructed, where N is the number of quaternions.
     272             :      * A weight matrix (W) is created. The eigenvector corresponding to the
     273             :      * maximum eigenvalue of Q*W*Q' is the weighted average quaternion
     274             :      */
     275             : 
     276             :     // quaternion average matrix Q*w*Q^T
     277             :     typedef Eigen::Matrix<Real, 4, 4> Matrix4x4;
     278             :     Matrix4x4 quat_mat = Matrix4x4::Zero();
     279             :     typedef Eigen::Matrix<Real, 4, 1> Vector4;
     280             : 
     281             :     bool data_quality_ok = false;
     282             :     Real total_weight = 0.0;
     283      296852 :     for (const auto & q : quat[i])
     284             :     {
     285             :       Vector4 v(q.w(), q.x(), q.y(), q.z());
     286             : 
     287      293306 :       const auto bin = std::make_tuple<int, int, int, int>(std::floor(q.w() * 0.5 * _bins),
     288      293306 :                                                            std::floor(q.x() * 0.5 * _bins),
     289      293306 :                                                            std::floor(q.y() * 0.5 * _bins),
     290      293306 :                                                            std::floor(q.z() * 0.5 * _bins));
     291      293306 :       const auto bin_size = feature_weights[bin];
     292      293306 :       const auto weight = std::pow(bin_size, _L_norm);
     293      293306 :       total_weight += weight;
     294             : 
     295      293306 :       quat_mat += v * weight * v.transpose();
     296             : 
     297             :       /**
     298             :        * If no bin exists which has at least 50% of total quaternions in a grain
     299             :        * then the EBSD data may not be reliable
     300             :        * Note: The limit 50% is arbitrary
     301             :        */
     302      293306 :       if (bin_size * 2 > quat[i].size())
     303             :         data_quality_ok = true;
     304             :     }
     305             : 
     306        3546 :     quat_mat *= 1.0 / total_weight;
     307             : 
     308             :     // throws a warning if EBSD data is not reliable
     309        3546 :     if (!data_quality_ok)
     310          35 :       _console << COLOR_YELLOW << "EBSD orientation data may not be reliable for grain " << i
     311          28 :                << '\n'
     312          35 :                << COLOR_DEFAULT << std::flush;
     313             : 
     314             :     // compute eigenvalues and eigenvectors
     315        3546 :     Eigen::EigenSolver<Matrix4x4> EigenSolver(quat_mat);
     316        3546 :     Vector4 eigen_values = EigenSolver.eigenvalues().real();
     317        3546 :     Matrix4x4 eigen_vectors = EigenSolver.eigenvectors().real();
     318             : 
     319             :     // Selecting eigenvector corresponding to max eigenvalue to compute average Euler angle
     320        3546 :     Vector4::Index max_index = 0;
     321             :     eigen_values.maxCoeff(&max_index);
     322        3546 :     const auto max_vec = eigen_vectors.col(max_index);
     323             :     const Eigen::Quaternion<Real> q(max_vec(0), max_vec(1), max_vec(2), max_vec(3));
     324        3546 :     b = EulerAngles(q);
     325             : 
     326             :     // link the EulerAngles into the EBSDAvgData for access via the functors
     327        3546 :     a._angles = &b;
     328             : 
     329        3546 :     if (a._phase >= _global_id.size())
     330         194 :       _global_id.resize(a._phase + 1);
     331             : 
     332             :     // The averaged per grain data locally contains the phase id, local id, and
     333             :     // original feature id. It is stored contiguously indexed by global id.
     334        3546 :     a._local_id = _global_id[a._phase].size();
     335        3546 :     _global_id[a._phase].push_back(i);
     336             : 
     337        3546 :     a._p *= 1.0 / Real(a._n);
     338             : 
     339        3546 :     for (unsigned int i = 0; i < _custom_columns; ++i)
     340           0 :       a._custom[i] /= Real(a._n);
     341             :   }
     342             :   // Build maps to indicate the weights with which grain and phase data
     343             :   // from the surrounding elements contributes to a node for IC purposes
     344         168 :   buildNodeWeightMaps();
     345         504 : }
     346             : 
     347         672 : EBSDReader::~EBSDReader() {}
     348             : 
     349             : const EBSDReader::EBSDPointData &
     350     1400456 : EBSDReader::getData(const Point & p) const
     351             : {
     352     1400456 :   return _data[indexFromPoint(p)];
     353             : }
     354             : 
     355             : const EBSDReader::EBSDAvgData &
     356      242848 : EBSDReader::getAvgData(unsigned int var) const
     357             : {
     358      242848 :   return _avg_data[indexFromIndex(var)];
     359             : }
     360             : 
     361             : const EulerAngles &
     362     1054190 : EBSDReader::getEulerAngles(unsigned int var) const
     363             : {
     364     1054190 :   return _avg_angles[indexFromIndex(var)];
     365             : }
     366             : 
     367             : const EBSDReader::EBSDAvgData &
     368       32539 : EBSDReader::getAvgData(unsigned int phase, unsigned int local_id) const
     369             : {
     370       32539 :   return _avg_data[indexFromIndex(_global_id[phase][local_id])];
     371             : }
     372             : 
     373             : unsigned int
     374     2056076 : EBSDReader::getGrainNum() const
     375             : {
     376     2056076 :   return _grain_num;
     377             : }
     378             : 
     379             : unsigned int
     380      840744 : EBSDReader::getGrainNum(unsigned int phase) const
     381             : {
     382      840744 :   return _global_id[phase].size();
     383             : }
     384             : 
     385             : unsigned int
     386     1693762 : EBSDReader::indexFromPoint(const Point & p) const
     387             : {
     388             :   // Don't assume an ordering on the input data, use the (x, y,
     389             :   // z) values of this centroid to determine the index.
     390             :   unsigned int x_index, y_index, z_index, global_index;
     391             : 
     392     1693762 :   x_index = (unsigned int)((p(0) - _minx) / _dx);
     393     1693762 :   y_index = (unsigned int)((p(1) - _miny) / _dy);
     394     1693762 :   if (p(0) <= _minx || p(0) >= _maxx || p(1) <= _miny || p(1) >= _maxy)
     395           0 :     mooseError("Data points must be on the interior of the mesh elements. In EBSDReader ", name());
     396             : 
     397     1693762 :   if (_mesh_dimension == 3)
     398             :   {
     399           0 :     z_index = (unsigned int)((p(2) - _minz) / _dz);
     400           0 :     global_index = z_index * _ny;
     401           0 :     if (p(2) <= _minz || p(2) >= _maxz)
     402           0 :       mooseError("Data points must be on the interior of the mesh elements. In EBSDReader ",
     403             :                  name());
     404             :   }
     405             :   else
     406             :     global_index = 0;
     407             : 
     408             :   // Compute the global index into the _data array.  This stores points
     409             :   // in a [z][y][x] ordering.
     410     1693762 :   global_index = (global_index + y_index) * _nx + x_index;
     411             : 
     412             :   // Don't access out of range!
     413             :   mooseAssert(global_index < _data.size(),
     414             :               "global_index " << global_index << " points out of _data range: " << _data.size());
     415             : 
     416     1693762 :   return global_index;
     417             : }
     418             : 
     419             : unsigned int
     420     1329577 : EBSDReader::indexFromIndex(unsigned int var) const
     421             : {
     422             : 
     423             :   // Transfer the index into the _avg_data array.
     424     1329577 :   unsigned avg_index = var;
     425             : 
     426             :   // Don't access out of range!
     427     1329577 :   if (avg_index >= _avg_data.size())
     428           0 :     mooseError("Error! Index out of range in EBSDReader::indexFromIndex(), index: ",
     429             :                avg_index,
     430             :                " size: ",
     431           0 :                _avg_data.size());
     432             : 
     433     1329577 :   return avg_index;
     434             : }
     435             : 
     436             : const std::map<dof_id_type, std::vector<Real>> &
     437         152 : EBSDReader::getNodeToGrainWeightMap() const
     438             : {
     439         152 :   return _node_to_grain_weight_map;
     440             : }
     441             : 
     442             : const std::map<dof_id_type, std::vector<Real>> &
     443          24 : EBSDReader::getNodeToPhaseWeightMap() const
     444             : {
     445          24 :   return _node_to_phase_weight_map;
     446             : }
     447             : 
     448             : unsigned int
     449     1159532 : EBSDReader::getGlobalID(unsigned int feature_id) const
     450             : {
     451             :   auto it = _global_id_map.find(feature_id);
     452     1159532 :   if (it == _global_id_map.end())
     453           0 :     mooseError("Invalid Feature ID");
     454     1159532 :   return it->second;
     455             : }
     456             : 
     457             : void
     458          16 : EBSDReader::meshChanged()
     459             : {
     460             :   // maps are only rebuild for use in initial conditions, which happens in time step zero
     461          16 :   if (_time_step == 0)
     462          16 :     buildNodeWeightMaps();
     463          16 : }
     464             : 
     465             : void
     466         184 : EBSDReader::buildNodeWeightMaps()
     467             : {
     468             :   // Import nodeToElemMap from MooseMesh for current node
     469             :   // This map consists of the node index followed by a vector of element indices that are associated
     470             :   // with that node
     471             :   const std::map<dof_id_type, std::vector<dof_id_type>> & node_to_elem_map =
     472         184 :       _mesh.nodeToActiveSemilocalElemMap();
     473         184 :   libMesh::MeshBase & mesh = _mesh.getMesh();
     474             : 
     475             :   // Loop through each node in mesh and calculate eta values for each grain associated with the node
     476      638814 :   for (const auto & node : as_range(mesh.active_nodes_begin(), mesh.active_nodes_end()))
     477             :   {
     478             :     // Get node_id
     479      319131 :     const dof_id_type node_id = node->id();
     480             : 
     481             :     // Initialize map entries for current node
     482      319131 :     _node_to_grain_weight_map[node_id].assign(getGrainNum(), 0.0);
     483      319131 :     _node_to_phase_weight_map[node_id].assign(getPhaseNum(), 0.0);
     484             : 
     485             :     // Loop through element indices associated with the current node and record weighted eta value
     486             :     // in new map
     487             :     const auto & node_to_elem_pair = node_to_elem_map.find(node_id);
     488      319131 :     if (node_to_elem_pair != node_to_elem_map.end())
     489             :     {
     490             :       unsigned int n_elems =
     491             :           node_to_elem_pair->second
     492      245634 :               .size(); // n_elems can range from 1 to 4 for 2D and 1 to 8 for 3D problems
     493             : 
     494     1179114 :       for (unsigned int ne = 0; ne < n_elems; ++ne)
     495             :       {
     496             :         // Current element index
     497      933480 :         unsigned int elem_id = (node_to_elem_pair->second)[ne];
     498             : 
     499             :         // Retrieve EBSD grain number for the current element index
     500      933480 :         const Elem * elem = mesh.elem_ptr(elem_id);
     501      933480 :         const EBSDReader::EBSDPointData & d = getData(elem->vertex_average());
     502             : 
     503             :         // get the (global) grain ID for the EBSD feature ID
     504      933480 :         const unsigned int global_id = getGlobalID(d._feature_id);
     505             : 
     506             :         // Calculate eta value and add to map
     507      933480 :         _node_to_grain_weight_map[node_id][global_id] += 1.0 / n_elems;
     508      933480 :         _node_to_phase_weight_map[node_id][d._phase] += 1.0 / n_elems;
     509             :       }
     510             :     }
     511         184 :   }
     512         184 : }
     513             : 
     514             : MooseSharedPointer<EBSDAccessFunctors::EBSDPointDataFunctor>
     515         344 : EBSDReader::getPointDataAccessFunctor(const MooseEnum & field_name) const
     516             : {
     517             :   EBSDPointDataFunctor * ret_val = NULL;
     518             : 
     519         344 :   switch (field_name)
     520             :   {
     521          66 :     case 0: // phi1
     522          66 :       ret_val = new EBSDPointDataPhi1();
     523             :       break;
     524          66 :     case 1: // phi
     525          66 :       ret_val = new EBSDPointDataPhi();
     526             :       break;
     527          66 :     case 2: // phi2
     528          66 :       ret_val = new EBSDPointDataPhi2();
     529             :       break;
     530         116 :     case 3: // grain
     531         116 :       ret_val = new EBSDPointDataFeatureID();
     532             :       break;
     533          18 :     case 4: // phase
     534          18 :       ret_val = new EBSDPointDataPhase();
     535             :       break;
     536          12 :     case 5: // symmetry
     537          12 :       ret_val = new EBSDPointDataSymmetry();
     538             :       break;
     539           0 :     default:
     540             :     {
     541             :       // check for custom columns
     542           0 :       for (const auto i : make_range(_custom_columns))
     543           0 :         if (field_name == "CUSTOM" + Moose::stringify(i))
     544             :         {
     545           0 :           ret_val = new EBSDPointDataCustom(i);
     546             :           break;
     547             :         }
     548             :     }
     549             :   }
     550             : 
     551             :   // If ret_val was not set by any of the above cases, throw an error.
     552             :   if (!ret_val)
     553           0 :     mooseError("Error:  Please input supported EBSD_param");
     554             : 
     555             :   // If we made it here, wrap up the the ret_val in a
     556             :   // MooseSharedPointer and ship it off.
     557         344 :   return MooseSharedPointer<EBSDPointDataFunctor>(ret_val);
     558             : }
     559             : 
     560             : MooseSharedPointer<EBSDAccessFunctors::EBSDAvgDataFunctor>
     561          36 : EBSDReader::getAvgDataAccessFunctor(const MooseEnum & field_name) const
     562             : {
     563             :   EBSDAvgDataFunctor * ret_val = NULL;
     564             : 
     565          36 :   switch (field_name)
     566             :   {
     567           0 :     case 0: // phi1
     568           0 :       ret_val = new EBSDAvgDataPhi1();
     569             :       break;
     570           0 :     case 1: // phi
     571           0 :       ret_val = new EBSDAvgDataPhi();
     572             :       break;
     573           0 :     case 2: // phi2
     574           0 :       ret_val = new EBSDAvgDataPhi2();
     575             :       break;
     576           0 :     case 3: // phase
     577           0 :       ret_val = new EBSDAvgDataPhase();
     578             :       break;
     579           0 :     case 4: // symmetry
     580           0 :       ret_val = new EBSDAvgDataSymmetry();
     581             :       break;
     582           0 :     case 5: // local_id
     583           0 :       ret_val = new EBSDAvgDataLocalID();
     584             :       break;
     585          36 :     case 6: // feature_id
     586          36 :       ret_val = new EBSDAvgDataFeatureID();
     587             :       break;
     588           0 :     default:
     589             :     {
     590             :       // check for custom columns
     591           0 :       for (const auto i : make_range(_custom_columns))
     592           0 :         if (field_name == "CUSTOM" + Moose::stringify(i))
     593             :         {
     594           0 :           ret_val = new EBSDAvgDataCustom(i);
     595             :           break;
     596             :         }
     597             :     }
     598             :   }
     599             : 
     600             :   // If ret_val was not set by any of the above cases, throw an error.
     601             :   if (!ret_val)
     602           0 :     mooseError("Error:  Please input supported EBSD_param");
     603             : 
     604             :   // If we made it here, wrap up the the ret_val in a
     605             :   // MooseSharedPointer and ship it off.
     606          36 :   return MooseSharedPointer<EBSDAvgDataFunctor>(ret_val);
     607             : }

Generated by: LCOV version 1.14