LCOV - code coverage report
Current view: top level - src/transfers - SCMSolutionTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose subchannel: #33187 (5aa0b2) with base d7c4bd Lines: 73 79 92.4 %
Date: 2026-06-30 12:24:57 Functions: 8 8 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 "SCMSolutionTransfer.h"
      11             : #include "MultiApp.h"
      12             : #include "FEProblemBase.h"
      13             : #include "DisplacedProblem.h"
      14             : #include "SubChannelMesh.h"
      15             : 
      16             : registerMooseObject("SubChannelApp", SCMSolutionTransfer);
      17             : registerMooseObjectRenamed("SubChannelApp",
      18             :                            SolutionTransfer,
      19             :                            "06/30/2027 24:00",
      20             :                            SCMSolutionTransfer);
      21             : registerMooseObjectRenamed("SubChannelApp",
      22             :                            SCMPinSolutionTransfer,
      23             :                            "06/30/2027 24:00",
      24             :                            SCMSolutionTransfer);
      25             : registerMooseObjectRenamed("SubChannelApp",
      26             :                            PinSolutionTransfer,
      27             :                            "06/30/2027 24:00",
      28             :                            SCMSolutionTransfer);
      29             : 
      30             : InputParameters
      31         250 : SCMSolutionTransfer::validParams()
      32             : {
      33         250 :   InputParameters params = MultiAppTransfer::validParams();
      34         500 :   params.addRequiredParam<std::vector<AuxVariableName>>("variable",
      35             :                                                         "The auxiliary variables to transfer.");
      36         500 :   MooseEnum transfer_type("subchannel pin", "subchannel");
      37         500 :   params.addParam<MooseEnum>("transfer_type",
      38             :                              transfer_type,
      39             :                              "Whether to transfer subchannel-centered or pin-centered fields.");
      40         250 :   params.addClassDescription(
      41             :       "Transfers subchannel or pin solutions from a SubChannel mesh onto a visualization mesh.");
      42         250 :   return params;
      43         250 : }
      44             : 
      45         125 : SCMSolutionTransfer::SCMSolutionTransfer(const InputParameters & parameters)
      46             :   : MultiAppTransfer(parameters),
      47         125 :     _var_names(getParam<std::vector<AuxVariableName>>("variable")),
      48         375 :     _pin_transfer(getParam<MooseEnum>("transfer_type") == "pin")
      49             : {
      50         125 :   if (_directions.contains(Transfer::FROM_MULTIAPP))
      51           0 :     paramError("from_multiapp", "This transfer works only into multi-app.");
      52         125 : }
      53             : 
      54             : void
      55         112 : SCMSolutionTransfer::initialSetup()
      56             : {
      57         112 :   MultiAppTransfer::initialSetup();
      58         699 :   for (std::size_t var_index = 0; var_index < _var_names.size(); ++var_index)
      59             :   {
      60         587 :     if (_to_problems.empty())
      61          16 :       continue;
      62             : 
      63         571 :     MooseVariableFieldBase & from_var = _subproblem.getVariable(
      64             :         0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
      65             :     const auto & fe_type = from_var.feType();
      66             : 
      67         571 :     if (fe_type.family != LAGRANGE || fe_type.order != FIRST)
      68           0 :       paramError("variable",
      69             :                  "This transfer requires a first order Lagrange variable for the source variable");
      70             : 
      71         571 :     MooseVariableFieldBase & to_var = _to_problems[0]->getVariable(
      72         571 :         0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
      73             :     const auto & fe_type_target = to_var.feType();
      74             : 
      75         571 :     if (fe_type_target.family != LAGRANGE || fe_type_target.order != FIRST)
      76           0 :       paramError("variable",
      77             :                  "This transfer requires a first order Lagrange variable for the source variable");
      78             :   }
      79         112 : }
      80             : 
      81             : void
      82         234 : SCMSolutionTransfer::execute()
      83             : {
      84         468 :   TIME_SECTION(
      85             :       "MultiAppDetailedSolutionBaseTransfer::execute()", 5, "Transferring subchannel solutions");
      86         234 :   getAppInfo();
      87             : 
      88         234 :   switch (_current_direction)
      89             :   {
      90         234 :     case TO_MULTIAPP:
      91             :     case BETWEEN_MULTIAPP:
      92         234 :       transferToMultiApps();
      93             :       break;
      94             : 
      95             :     default:
      96             :       break;
      97             :   }
      98         234 : }
      99             : 
     100             : void
     101         234 : SCMSolutionTransfer::transferToMultiApps()
     102             : {
     103             :   mooseAssert(_from_meshes.size() == 1, "Only one source mesh can be active in this transfer.");
     104         234 :   auto * from_mesh = dynamic_cast<SubChannelMesh *>(_from_meshes[0]);
     105         234 :   if (from_mesh == nullptr)
     106           0 :     mooseError("This transfer works only with SubChannelMesh classes.");
     107         234 :   if (_pin_transfer && !from_mesh->pinMeshExist())
     108           0 :     mooseError(
     109             :         "This transfer was configured for pin variables, but the source mesh has no pin mesh.");
     110             : 
     111         936 :   for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++)
     112         468 :     if (getToMultiApp()->hasLocalApp(i))
     113         226 :       transferVarsToApp(i);
     114         234 : }
     115             : 
     116             : void
     117         226 : SCMSolutionTransfer::transferVarsToApp(unsigned int app_idx)
     118             : {
     119         226 :   transferNodalVars(app_idx);
     120         226 : }
     121             : 
     122             : void
     123         226 : SCMSolutionTransfer::transferNodalVars(unsigned int app_idx)
     124             : {
     125         226 :   Moose::ScopedCommSwapper swapper(getToMultiApp()->comm());
     126             : 
     127         226 :   FEProblemBase & to_problem = getToMultiApp()->appProblemBase(app_idx);
     128             :   MooseMesh * mesh = NULL;
     129         226 :   if (_displaced_target_mesh && to_problem.getDisplacedProblem())
     130           0 :     mesh = &to_problem.getDisplacedProblem()->mesh();
     131             :   else
     132         226 :     mesh = &to_problem.mesh();
     133             : 
     134         226 :   const SubChannelMesh & from_mesh = dynamic_cast<SubChannelMesh &>(*_from_meshes[0]);
     135         226 :   FEProblemBase & from_problem = *_from_problems[0];
     136             : 
     137     7755284 :   for (auto & node : mesh->getMesh().local_node_ptr_range())
     138             :   {
     139     3877416 :     if (processor_id() != 0)
     140      881254 :       continue;
     141     2996162 :     Node * from_node = getFromNode(from_mesh, *node);
     142             : 
     143    19022473 :     for (auto & var_name : _var_names)
     144             :     {
     145    16026311 :       System * to_sys = find_sys(to_problem.es(), var_name);
     146             :       unsigned int to_sys_num = to_sys->number();
     147    16026311 :       unsigned int to_var_num = to_sys->variable_number(var_name);
     148             : 
     149    16026311 :       if (node->n_dofs(to_sys_num, to_var_num) > 0)
     150             :       {
     151    13744207 :         System * from_sys = find_sys(from_problem.es(), var_name);
     152             :         unsigned int from_sys_num = from_sys->number();
     153    13744207 :         unsigned int from_var_num = from_sys->variable_number(var_name);
     154             : 
     155             :         // Return to parent app MPI communicator to get solution dof
     156             :         swapper.forceSwap();
     157             :         NumericVector<Real> * from_solution = from_sys->solution.get();
     158    13744207 :         dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
     159    13744207 :         Real from_value = (*from_solution)(from_dof);
     160             :         swapper.forceSwap();
     161             : 
     162    27488414 :         NumericVector<Real> & to_solution = getToMultiApp()->appTransferVector(app_idx, var_name);
     163    13744207 :         dof_id_type to_dof = node->dof_number(to_sys_num, to_var_num, 0);
     164    13744207 :         to_solution.set(to_dof, from_value);
     165             :       }
     166             :     }
     167         226 :   }
     168             : 
     169        1397 :   for (auto & var_name : _var_names)
     170             :   {
     171        2342 :     getToMultiApp()->appTransferVector(app_idx, var_name).close();
     172        1171 :     find_sys(to_problem.es(), var_name)->update();
     173             :   }
     174         226 : }
     175             : 
     176             : Node *
     177     2996162 : SCMSolutionTransfer::getFromNode(const SubChannelMesh & from_mesh, const Point & src_node)
     178             : {
     179             :   unsigned int sch_idx =
     180     2996162 :       _pin_transfer ? from_mesh.pinIndex(src_node) : from_mesh.channelIndex(src_node);
     181     2996162 :   unsigned iz = from_mesh.getZIndex(src_node);
     182     2996162 :   return _pin_transfer ? from_mesh.getPinNode(sch_idx, iz) : from_mesh.getChannelNode(sch_idx, iz);
     183             : }

Generated by: LCOV version 1.14