LCOV - code coverage report
Current view: top level - src/auxkernels - ProjectionAux.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 55 59 93.2 %
Date: 2026-05-29 20:35:17 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 "ProjectionAux.h"
      11             : #include "SystemBase.h"
      12             : #include "libmesh/system.h"
      13             : 
      14             : registerMooseObjectRenamed("MooseApp", SelfAux, "01/30/2024 24:00", ProjectionAux);
      15             : registerMooseObject("MooseApp", ProjectionAux);
      16             : 
      17             : InputParameters
      18       14121 : ProjectionAux::validParams()
      19             : {
      20       14121 :   InputParameters params = AuxKernel::validParams();
      21       28242 :   params.addClassDescription(
      22             :       "Returns the specified variable as an auxiliary variable with a projection of the source "
      23             :       "variable. If they are the same type, this amounts to a simple copy.");
      24       56484 :   params.addRequiredCoupledVar("v", "Variable to take the value of.");
      25             : 
      26       42363 :   params.addParam<bool>("use_block_restriction_for_source",
      27       28242 :                         false,
      28             :                         "Whether to use the auxkernel block restriction to also restrict the "
      29             :                         "locations selected for source variable values");
      30             : 
      31             :   // Technically possible to project from nodal to elemental and back
      32       28242 :   params.set<bool>("_allow_nodal_to_elemental_coupling") = true;
      33             : 
      34       56484 :   MooseEnum elem_to_node_projection_weighting("volume identity", "volume");
      35       42363 :   params.addParam<MooseEnum>("elem_to_node_projection_weighting",
      36             :                              elem_to_node_projection_weighting,
      37             :                              "How to weight individual element contributions when projecting to a "
      38             :                              "nodal degree of freedom");
      39             : 
      40             :   // We need some ghosting for all elemental to nodal projections
      41       42363 :   params.addRelationshipManager(
      42             :       "GhostAllPointNeighbors",
      43             :       Moose::RelationshipManagerType::GEOMETRIC | Moose::RelationshipManagerType::ALGEBRAIC,
      44           0 :       [](const InputParameters & obj_params, InputParameters & rm_params)
      45       34407 :       { rm_params.set<bool>("use_displaced_mesh") = obj_params.get<bool>("use_displaced_mesh"); });
      46       28242 :   return params;
      47       14121 : }
      48             : 
      49        4164 : ProjectionAux::ProjectionAux(const InputParameters & parameters)
      50             :   : AuxKernel(parameters),
      51        4164 :     _v(coupledValue("v")),
      52        8328 :     _source_variable(*getFieldVar("v", 0)),
      53        8328 :     _source_sys(_c_fe_problem.getSystem(coupledName("v"))),
      54        8328 :     _use_block_restriction_for_source(getParam<bool>("use_block_restriction_for_source")),
      55       12492 :     _elem_to_node_projection_weighting(getParam<MooseEnum>("elem_to_node_projection_weighting")
      56       12492 :                                            .getEnum<ElemToNodeProjectionWeighting>())
      57             : {
      58             :   // Output some messages to user
      59        4164 :   if (_source_variable.order() > _var.order())
      60        1523 :     mooseInfo("Projection lowers order, please expect a loss of accuracy");
      61        4164 : }
      62             : 
      63             : Real
      64    12635935 : ProjectionAux::computeValue()
      65             : {
      66    12635935 :   if (!isNodal() || (_source_variable.isNodal() && _source_variable.order() >= _var.order()))
      67    12482399 :     return _v[_qp];
      68             :   // projecting continuous variable onto a nodal one
      69             :   // AND projecting from low order -> nodal higher order
      70      191256 :   else if (isNodal() && _source_variable.getContinuity() != DISCONTINUOUS &&
      71       37720 :            _source_variable.getContinuity() != SIDE_DISCONTINUOUS)
      72       75440 :     return _source_sys.point_value(
      73       75440 :         _source_variable.number(), *_current_node, elemOnNodeVariableIsDefinedOn());
      74             :   // Handle discontinuous elemental variable projection into a nodal variable
      75             :   else
      76             :   {
      77             :     // Custom projection rule : use nodal values, if discontinuous the one coming from each element,
      78             :     // weighted by element volumes
      79             :     // First, find all the elements that this node is part of
      80      115816 :     const auto & elem_ids = libmesh_map_find(_mesh.nodeToElemMap(), _current_node->id());
      81             : 
      82             :     // Get the neighbor element centroid values & element volumes
      83      115816 :     Real sum_weighted_values = 0;
      84      115816 :     Real sum_weights = 0;
      85      115816 :     _elem_dims.clear();
      86      514872 :     for (const auto id : elem_ids)
      87             :     {
      88      399056 :       const auto * const elem = _mesh.elemPtr(id);
      89      399056 :       const auto block_id = elem->subdomain_id();
      90      798112 :       if (_source_variable.hasBlocks(block_id) &&
      91      399056 :           (!_use_block_restriction_for_source || hasBlocks(block_id)))
      92             :       {
      93      398864 :         if (_elem_to_node_projection_weighting == ProjectionAux::VOLUME)
      94      398864 :           _elem_dims.insert(elem->dim());
      95             :         const auto elem_weight =
      96      398864 :             _elem_to_node_projection_weighting == ProjectionAux::VOLUME ? elem->volume() : 1.;
      97      398864 :         sum_weighted_values +=
      98      398864 :             _source_sys.point_value(_source_variable.number(), *_current_node, elem) * elem_weight;
      99      398864 :         sum_weights += elem_weight;
     100             :       }
     101             :     }
     102      115816 :     if (sum_weights == 0)
     103           0 :       mooseError("Did not find a valid source variable value for node: ", *_current_node);
     104      115816 :     if ((_elem_to_node_projection_weighting == ProjectionAux::VOLUME) && (_elem_dims.size() > 1))
     105           0 :       mooseError("We should not use multiple element dimensions when computing the volume weighted "
     106             :                  "projection as the units do not make sense");
     107      115816 :     return sum_weighted_values / sum_weights;
     108             :   }
     109             : }
     110             : 
     111             : const Elem *
     112       37720 : ProjectionAux::elemOnNodeVariableIsDefinedOn() const
     113             : {
     114       37720 :   for (const auto & elem_id : _mesh.nodeToElemMap().find(_current_node->id())->second)
     115             :   {
     116       37720 :     const auto & elem = _mesh.elemPtr(elem_id);
     117       37720 :     const auto block_id = elem->subdomain_id();
     118       75440 :     if (_source_variable.hasBlocks(block_id) &&
     119       37720 :         (!_use_block_restriction_for_source || hasBlocks(block_id)))
     120       37720 :       return elem;
     121             :   }
     122           0 :   mooseError("Source variable is not defined everywhere the target variable is");
     123             : }

Generated by: LCOV version 1.14