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 "NearestNodeValueAux.h" 11 : 12 : #include "SystemBase.h" 13 : #include "NearestNodeLocator.h" 14 : 15 : registerMooseObject("MooseApp", NearestNodeValueAux); 16 : 17 : InputParameters 18 14292 : NearestNodeValueAux::validParams() 19 : { 20 14292 : InputParameters params = AuxKernel::validParams(); 21 28584 : params.addClassDescription("Retrieves a field value from the closest node on the paired boundary " 22 : "and stores it on this boundary or block."); 23 28584 : params.set<bool>("_dual_restrictable") = true; 24 57168 : params.addRequiredParam<BoundaryName>("paired_boundary", "The boundary to get the value from."); 25 57168 : params.addRequiredCoupledVar("paired_variable", "The variable to get the value of."); 26 14292 : params.set<bool>("use_displaced_mesh") = true; 27 14292 : return params; 28 0 : } 29 : 30 14 : NearestNodeValueAux::NearestNodeValueAux(const InputParameters & parameters) 31 : : AuxKernel(parameters), 32 14 : _nearest_node( 33 14 : getNearestNodeLocator(parameters.get<BoundaryName>("paired_boundary"), boundaryNames()[0])), 34 14 : _serialized_solution(_nl_sys.currentSolution()), 35 42 : _paired_variable(coupled("paired_variable")) 36 : { 37 14 : if (boundaryNames().size() > 1) 38 0 : paramError("boundary", "NearestNodeValueAux can only be used with one boundary at a time!"); 39 14 : if (boundaryNames().empty()) 40 0 : paramError("boundary", "Should be specified on a boundary"); 41 : 42 : // Check that the paired variable is from the solution system 43 42 : if (_subproblem.hasAuxiliaryVariable("paired_variable")) 44 0 : paramError("paired_variable", "Paired variable should not be auxiliary"); 45 : // Check that the paired variable has degrees of freedom on nodes (and thus can be sampled 46 : // directly at the dof index of the node) 47 42 : if (!getVar("paired_variable", 0)->hasDoFsOnNodes()) 48 0 : paramError("paired_variable", "Paired variable does not have degrees of freedom on nodes"); 49 : 50 : // TODO: avoid the runtime checks by making sure the paired variable is defined on the boundaries 51 14 : } 52 : 53 : Real 54 476 : NearestNodeValueAux::computeValue() 55 : { 56 476 : if (isNodal()) 57 : { 58 : // Assumes the variable you are coupling to is from the nonlinear system for now. 59 476 : const Node * nearest = _nearest_node.nearestNode(_current_node->id()); 60 476 : if (nearest == nullptr) 61 0 : mooseError("Could not locate the nearest node from node: ", _current_node->get_info()); 62 476 : dof_id_type dof_number = nearest->dof_number(_nl_sys.number(), _paired_variable, 0); 63 476 : if (dof_number == libMesh::DofObject::invalid_id) 64 0 : mooseError("Paired variable does not seem to be defined on nearest node: ", 65 0 : nearest->get_info()); 66 476 : return (*_serialized_solution)(dof_number); 67 : } 68 : else 69 : { 70 : // Get a value for all the nodes on the boundary, then average them for the centroid value 71 0 : Real average = 0; 72 0 : Real sum_inv_dist = 0; 73 0 : for (const auto & node : _current_elem->node_ref_range()) 74 : { 75 0 : const Node * nearest = _nearest_node.nearestNode(node.id()); 76 : // Some of the element's nodes wont be on the boundary 77 0 : if (!nearest) 78 0 : continue; 79 0 : const auto dof_number = nearest->dof_number(_nl_sys.number(), _paired_variable, 0); 80 0 : const auto distance = _nearest_node.distance(node.id()); 81 : 82 0 : if (dof_number == libMesh::DofObject::invalid_id) 83 0 : mooseError("Paired variable does not seem to be defined on nearest node: ", 84 0 : nearest->get_info()); 85 : 86 : // inverse distance weighting should be a fine default 87 0 : if (distance > 0) 88 : { 89 0 : average += (*_serialized_solution)(dof_number) / distance; 90 0 : sum_inv_dist += 1. / distance; 91 : } 92 : // if node and nearest nodes coincide, weight with 1 93 : else 94 : { 95 0 : average += (*_serialized_solution)(dof_number); 96 0 : sum_inv_dist += 1.; 97 : } 98 : } 99 : 100 0 : if (sum_inv_dist > 0) 101 0 : return average / sum_inv_dist; 102 : else 103 0 : return 0.; 104 : } 105 : }