Skip to content

Commit

Permalink
NearestNodeNumber postprocessor added. Refs idaholab#15749
Browse files Browse the repository at this point in the history
  • Loading branch information
WilkAndy committed Oct 8, 2020
1 parent fbe1a3c commit eb6efdf
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# NearestNodeNumber

The postprocessor outputs the node number of the nearest node to a given point. It is used by the [GeochemistryConsoleOutput](GeochemistryConsoleOutput.md) object to identify the node at which output is required.

!alert note
You will probably want to set execute_on to initial to avoid unnecessary computations, unless you have adaptive meshing, in which case set execute_on to initial and timestep_begin.

!syntax parameters /Postprocessors/NearestNodeNumber

!syntax inputs /Postprocessors/NearestNodeNumber

!syntax children /Postprocessors/NearestNodeNumber

62 changes: 62 additions & 0 deletions modules/geochemistry/include/postprocessors/NearestNodeNumber.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "NodalPostprocessor.h"

/**
* Finds the nearest node number to a given point. Upon a tie, the node with the smallest id() is
* used
*/
class NearestNodeNumber : public NodalPostprocessor
{
public:
static InputParameters validParams();

NearestNodeNumber(const InputParameters & parameters);

virtual void meshChanged() override;
virtual void initialize() override;
virtual void execute() override;
virtual void finalize() override;
virtual Real getValue() override;
virtual void threadJoin(const UserObject & y) override;

/**
* Returns a const pointer to the closest node over the entire mesh, if that node is owned by this
* processor, otherwise returns nullptr
*/
const Node * getClosestNode();

private:
/// processor ID of this object
const processor_id_type _my_pid;

/// The point
const Point & _point;

/// Whether the nearest node on this processor has been found (this is used to reduce unnecessary re-computations)
bool _node_found;

/// Minimum distance for nodes on this processor
Real _min_distance;

/// Nearest node on this processor
const Node * _closest_node;

/// Node number of closest node, over the whole mesh
dof_id_type _overall_best_id;

/**
* Perform MPI communication to find _overall_best_id, which is the node id of the closest node,
* and if there is a tie then the the lowest nodal id is used
*/
void computeOverallBestId();
};
110 changes: 110 additions & 0 deletions modules/geochemistry/src/postprocessors/NearestNodeNumber.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "NearestNodeNumber.h"
#include <limits>

registerMooseObject("GeochemistryApp", NearestNodeNumber);

InputParameters
NearestNodeNumber::validParams()
{
InputParameters params = NodalPostprocessor::validParams();
params.addRequiredParam<Point>("point", "The point");
params.addClassDescription("Finds and outputs the nearest node number to a point");
return params;
}

NearestNodeNumber::NearestNodeNumber(const InputParameters & parameters)
: NodalPostprocessor(parameters),
_my_pid(processor_id()),
_point(getParam<Point>("point")),
_node_found(false),
_min_distance(std::numeric_limits<Real>::max()),
_closest_node(nullptr)
{
}

void
NearestNodeNumber::meshChanged()
{
_node_found = false;
_min_distance = std::numeric_limits<Real>::max();
_closest_node = nullptr;
}

void
NearestNodeNumber::initialize()
{
if (!_node_found)
{
_min_distance = std::numeric_limits<Real>::max();
_closest_node = nullptr;
}
}

void
NearestNodeNumber::execute()
{
if (_node_found)
return;
const Real dist = ((*_current_node) - _point).norm();
if (dist < _min_distance || (dist == _min_distance && _current_node->id() < _closest_node->id()))
{
_min_distance = dist;
_closest_node = _current_node;
}
}

void
NearestNodeNumber::finalize()
{
_node_found = true;
}

Real
NearestNodeNumber::getValue()
{
computeOverallBestId();
return _overall_best_id;
}

void
NearestNodeNumber::computeOverallBestId()
{
Real overall_min_distance = _min_distance;
gatherMin(overall_min_distance);
_overall_best_id = (overall_min_distance == _min_distance)
? _closest_node->id()
: std::numeric_limits<dof_id_type>::max();
gatherMin(_overall_best_id);
}

const Node *
NearestNodeNumber::getClosestNode()
{
computeOverallBestId();
if (_closest_node->id() == _overall_best_id && _closest_node->processor_id() == _my_pid)
return _closest_node;
return nullptr;
}

void
NearestNodeNumber::threadJoin(const UserObject & y)
{
const NearestNodeNumber & nnn = static_cast<const NearestNodeNumber &>(y);
if (!nnn._closest_node)
return;
if (nnn._min_distance < _min_distance ||
(nnn._min_distance == _min_distance && nnn._closest_node->id() < _closest_node->id()))
{
_min_distance = nnn._min_distance;
_closest_node = nnn._closest_node;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
time,nnn
0,1
1,1
2,1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
time,nnn
0,4
1,4
2,4
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
time,nnn
0,1
1,1
2,1
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Using NearestNodeNumber, finds the node number of the nearest node to the point in the mesh
# In this case, the point is coincident with node number 1
[Mesh]
type = GeneratedMesh
dim = 1
nx = 4
xmax = 8
[]

[Postprocessors]
[./nnn]
type = NearestNodeNumber
point = '2 0 0'
execute_on = 'initial timestep_begin'
[../]
[]

[Problem]
solve = false
[]

[Executioner]
type = Transient
end_time = 2
[]

[Outputs]
csv = true
[]



Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Using NearestNodeNumber, finds the node number of the nearest node to the point in the mesh
# In this case, the mesh has two disjoint parts and the point is equidistant from the two parts, so the closest node with the smallest ID is chosen.
# This input file is run multiple times:
# - 1 thread and 1 process
# - 2 threads and 1 process
# - 1 thread and 2 processes
# - 2 threads and 2 processes
# Each time should give the same result
[Mesh]
[./left]
type = GeneratedMeshGenerator
dim = 1
nx = 4
xmin = 0
xmax = 8
[../]
[./right]
type = GeneratedMeshGenerator
dim = 1
nx = 4
xmin = 12
xmax = 20
[../]
[./combiner]
type = CombinerGenerator
inputs = 'left right'
[../]
[]

[Postprocessors]
[./nnn]
type = NearestNodeNumber
point = '10 0 0'
execute_on = 'initial timestep_begin'
[../]
[]

[Problem]
solve = false
[]

[Executioner]
type = Transient
end_time = 2
[]

[Outputs]
csv = true
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Using NearestNodeNumber, finds the node number of the nearest node to the point in the mesh
# In this case, the point is coincident with node number 1, but then adaptivity changes this
[Mesh]
type = GeneratedMesh
dim = 2
ny = 1
nx = 4
xmax = 8
[]

[Adaptivity]
marker = marker
[Markers]
[./marker]
type = BoxMarker
bottom_left = '0 0 0'
top_right = '8 1 0'
inside = refine
outside = do_nothing
[../]
[]
[]

[Postprocessors]
[./nnn]
type = NearestNodeNumber
point = '2 0 0'
execute_on = 'initial timestep_begin'
[../]
[]

[Problem]
solve = false
[]

[Executioner]
type = Transient
end_time = 2
[]

[Outputs]
csv = true
[]
51 changes: 51 additions & 0 deletions modules/geochemistry/test/tests/postprocessors/tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
issues = '#15749'
design = 'NearestNodeNumber.md'
[Tests]
[./nearest_node_number_1]
type = CSVDiff
input = nearest_node_number_1.i
csvdiff = nearest_node_number_1_out.csv
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point."
[../]
[./nearest_node_number_2]
type = CSVDiff
input = nearest_node_number_2.i
csvdiff = nearest_node_number_2_out.csv
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point, and will choose the smallest node number if more than one node is equidistant."
[../]
[./nearest_node_number_2_2threads]
type = CSVDiff
input = nearest_node_number_2.i
csvdiff = nearest_node_number_2_out.csv
prereq = nearest_node_number_2
min_threads = 2
max_threads = 2
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point, and will choose the smallest node number if more than one node is equidistant."
[../]
[./nearest_node_number_2_2procs]
type = CSVDiff
input = nearest_node_number_2.i
csvdiff = nearest_node_number_2_out.csv
prereq = nearest_node_number_2_2threads
min_parallel = 2
max_parallel = 2
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point, and will choose the smallest node number if more than one node is equidistant."
[../]
[./nearest_node_number_2_2procs_2threads]
type = CSVDiff
input = nearest_node_number_2.i
csvdiff = nearest_node_number_2_out.csv
prereq = nearest_node_number_2_2procs
min_parallel = 2
max_parallel = 2
min_threads = 2
max_threads = 2
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point, and will choose the smallest node number if more than one node is equidistant."
[../]
[./nearest_node_number_3]
type = CSVDiff
input = nearest_node_number_3.i
csvdiff = nearest_node_number_3_out.csv
requirement = "The geochemistry module shall contain a postprocessor that can compute the nearest node number to a given point, including when the mesh is adapting"
[../]
[]

0 comments on commit eb6efdf

Please sign in to comment.