LCOV - code coverage report
Current view: top level - src/auxkernels - EulerAngleProvider2RGBAux.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 48 54 88.9 %
Date: 2025-09-04 07:55:36 Functions: 5 5 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 "EulerAngleProvider2RGBAux.h"
      11             : #include "GrainTracker.h"
      12             : #include "EulerAngleProvider.h"
      13             : #include "Euler2RGB.h"
      14             : #include "EBSDReader.h"
      15             : 
      16             : registerMooseObject("PhaseFieldApp", EulerAngleProvider2RGBAux);
      17             : 
      18             : InputParameters
      19         174 : EulerAngleProvider2RGBAux::validParams()
      20             : {
      21         174 :   InputParameters params = AuxKernel::validParams();
      22         174 :   params.addClassDescription("Output RGB representation of crystal orientation from user object to "
      23             :                              "an AuxVariable. The entire domain must have the same crystal "
      24             :                              "structure.");
      25         348 :   params.addParam<unsigned int>("phase", "The phase to use for all queries.");
      26         348 :   MooseEnum sd_enum = MooseEnum("100=1 010=2 001=3", "001");
      27         348 :   params.addParam<MooseEnum>("sd", sd_enum, "Reference sample direction");
      28             :   MooseEnum structure_enum = MooseEnum(
      29         348 :       "cubic=43 hexagonal=62 tetragonal=42 trigonal=32 orthorhombic=22 monoclinic=2 triclinic=1");
      30         348 :   params.addRequiredParam<MooseEnum>(
      31             :       "crystal_structure", structure_enum, "Crystal structure of the material");
      32         348 :   MooseEnum output_types = MooseEnum("red green blue scalar", "scalar");
      33         348 :   params.addParam<MooseEnum>("output_type", output_types, "Type of value that will be outputted");
      34         348 :   params.addRequiredParam<UserObjectName>("euler_angle_provider",
      35             :                                           "Name of Euler angle provider user object");
      36         348 :   params.addRequiredParam<UserObjectName>("grain_tracker",
      37             :                                           "The GrainTracker UserObject to get values from.");
      38         174 :   params.addParam<Point>(
      39             :       "no_grain_color",
      40         174 :       Point(0, 0, 0),
      41             :       "RGB value of color used to represent area with no grains, defaults to black");
      42         174 :   return params;
      43         174 : }
      44             : 
      45          93 : EulerAngleProvider2RGBAux::EulerAngleProvider2RGBAux(const InputParameters & parameters)
      46             :   : AuxKernel(parameters),
      47         165 :     _phase(isParamValid("phase") ? getParam<unsigned int>("phase") : libMesh::invalid_uint),
      48         186 :     _sd(getParam<MooseEnum>("sd")),
      49         186 :     _xtal_class(getParam<MooseEnum>("crystal_structure")),
      50         186 :     _output_type(getParam<MooseEnum>("output_type")),
      51          93 :     _euler(getUserObject<EulerAngleProvider>("euler_angle_provider")),
      52         186 :     _ebsd_reader(isParamValid("phase") ? dynamic_cast<const EBSDReader *>(&_euler) : nullptr),
      53          93 :     _grain_tracker(dynamic_cast<const GrainTrackerInterface &>(getUserObjectBase("grain_tracker"))),
      54         279 :     _no_grain_color(getParam<Point>("no_grain_color"))
      55             : {
      56          93 : }
      57             : 
      58             : unsigned int
      59      145326 : EulerAngleProvider2RGBAux::getNumGrains() const
      60             : {
      61      145326 :   if (_phase != libMesh::invalid_uint)
      62       97617 :     return _ebsd_reader->getGrainNum(_phase);
      63             :   else
      64       47709 :     return _euler.getGrainNum();
      65             : }
      66             : 
      67             : void
      68      157260 : EulerAngleProvider2RGBAux::precalculateValue()
      69             : {
      70             :   const auto grain_id =
      71      157260 :       _grain_tracker.getEntityValue(isNodal() ? _current_node->id() : _current_elem->id(),
      72             :                                     FeatureFloodCount::FieldType::UNIQUE_REGION,
      73             :                                     0);
      74             : 
      75             :   // Recover Euler angles for current grain and assign correct RGB value either
      76             :   // from Euler2RGB or from _no_grain_color
      77             :   Point RGB;
      78      157260 :   if (grain_id < 0)
      79       11934 :     RGB = _no_grain_color;
      80             :   else
      81             :   {
      82             :     /* The grain index retrieved from FeatureFloodCount is the "global_id" unless
      83             :        the "phase" option is used in the simulation.  For the phase dependent case,
      84             :        the returned grain index is the "local_id." This must be converted to a
      85             :        "global_id" using the getGlobalID function of EBSDREader before the Euler
      86             :        Angles are retrieved. */
      87             : 
      88             :     auto global_id =
      89      145326 :         _phase != libMesh::invalid_uint ? _ebsd_reader->getGlobalID(_phase, grain_id) : grain_id;
      90      145326 :     const auto num_grns = getNumGrains();
      91      145326 :     if (global_id > num_grns)
      92           0 :       mooseError(" global_id ", global_id, " out of index range");
      93             : 
      94             :     // Retrieve Euler Angle values from the EulerAngleProvider
      95      145326 :     const RealVectorValue & angles = _euler.getEulerAngles(global_id);
      96             : 
      97             :     // Convert Euler Angle values to RGB colorspace for visualization purposes
      98      145326 :     RGB = euler2RGB(_sd,
      99      145326 :                     angles(0) / 180.0 * libMesh::pi,
     100      145326 :                     angles(1) / 180.0 * libMesh::pi,
     101      145326 :                     angles(2) / 180.0 * libMesh::pi,
     102             :                     1.0,
     103      145326 :                     _xtal_class);
     104             :   }
     105             : 
     106             :   // Create correct scalar output
     107      157260 :   if (_output_type < 3)
     108      157260 :     _value = RGB(_output_type);
     109           0 :   else if (_output_type == 3)
     110             :   {
     111             :     Real RGBint = 0.0;
     112           0 :     for (unsigned int i = 0; i < 3; ++i)
     113           0 :       RGBint = 256 * RGBint + (RGB(i) >= 1 ? 255 : std::floor(RGB(i) * 256.0));
     114           0 :     _value = RGBint;
     115             :   }
     116             :   else
     117           0 :     mooseError("Incorrect value for output_type in EulerAngleProvider2RGBAux");
     118      157260 : }
     119             : 
     120             : Real
     121      629040 : EulerAngleProvider2RGBAux::computeValue()
     122             : {
     123      629040 :   return _value;
     124             : }

Generated by: LCOV version 1.14