Skip to content

Commit

Permalink
Add SidesetInfoVectorPostprocessor (idaholab#14275)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Schunert authored and Sebastian Schunert committed Nov 2, 2019
1 parent dcbc846 commit a96ff79
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 0 deletions.
@@ -0,0 +1,19 @@
# SidesetInfoVectorPostprocessor

!syntax description /VectorPostprocessors/SidesetInfoVectorPostprocessor

## Description

SidesetInfoVectorPostprocessor assembles information from sidesets and prints them to
a csv file. Currently, it allows to obtain `area`, `centroid`, and the bounding box
via `min` and `max`. `min` contains the minimum x, y, z coordinates of the
sideset, while `max` contains the respective maximum values. Note that `centroid`
is not guaranteed to be a point contained in the sideset.

!syntax parameters /VectorPostprocessors/SidesetInfoVectorPostprocessor

!syntax inputs /VectorPostprocessors/SidesetInfoVectorPostprocessor

!syntax children /VectorPostprocessors/SidesetInfoVectorPostprocessor

!bibtex bibliography
@@ -0,0 +1,68 @@
//* 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 "SideVectorPostprocessor.h"

// Forward Declarations
class SidesetInfoVectorPostprocessor;

template <>
InputParameters validParams<SidesetInfoVectorPostprocessor>();

class SidesetInfoVectorPostprocessor : public SideVectorPostprocessor
{
public:
SidesetInfoVectorPostprocessor(const InputParameters & parameters);

virtual void initialize() override;
virtual void execute() override;
virtual void finalize() override;

virtual void threadJoin(const UserObject & y) override;

struct BoundaryData
{
BoundaryData()
: area(0),
centroid(Point()),
min(Point(std::numeric_limits<Real>::max(),
std::numeric_limits<Real>::max(),
std::numeric_limits<Real>::max())),
max(Point(std::numeric_limits<Real>::lowest(),
std::numeric_limits<Real>::lowest(),
std::numeric_limits<Real>::lowest()))
{
}
Real area;
Point centroid;
Point min;
Point max;
};

protected:
/// a helper function for retrieving data from _boundary_info
Real dataHelper(BoundaryID bid, std::string mdat_tpe) const;

/// the type of meta data that is written to file
MultiMooseEnum _meta_data_types;

/// the type of meta data that is written to file
std::vector<std::string> _vpp_entry_names;

/// the sideset id
VectorPostprocessorValue & _sideset_ids;

/// the vpp data is stored here
std::vector<VectorPostprocessorValue *> _meta_data;

/// all data available through the meta_data_types is always accumulated
std::map<BoundaryID, BoundaryData> _boundary_data;
};
192 changes: 192 additions & 0 deletions framework/src/vectorpostprocessors/SidesetInfoVectorPostprocessor.C
@@ -0,0 +1,192 @@
//* 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 "SidesetInfoVectorPostprocessor.h"
#include <limits>

#include "libmesh/quadrature.h"

registerMooseObject("MooseApp", SidesetInfoVectorPostprocessor);

template <>
InputParameters
validParams<SidesetInfoVectorPostprocessor>()
{
InputParameters params = validParams<SideVectorPostprocessor>();
MultiMooseEnum meta_data_types("centroid=0 min=1 max=2 area=3");
params.addParam<MultiMooseEnum>(
"meta_data_types", meta_data_types, "Data types that are obtained and written to file.");
params.addClassDescription("This VectorPostprocessor collects meta data for provided sidesets.");
return params;
}

SidesetInfoVectorPostprocessor::SidesetInfoVectorPostprocessor(const InputParameters & parameters)
: SideVectorPostprocessor(parameters),
_meta_data_types(getParam<MultiMooseEnum>("meta_data_types")),
_sideset_ids(declareVector("Boundary IDs"))
{
// this sets up the _vpp_entry_names vector
for (unsigned int j = 0; j < _meta_data_types.size(); ++j)
{
if (_meta_data_types[j] == "centroid" || _meta_data_types[j] == "min" ||
_meta_data_types[j] == "max")
{
for (unsigned int d = 0; d < _mesh.dimension(); ++d)
{
std::stringstream ss;
ss << _meta_data_types[j] << "_";
if (d == 0)
ss << "x";
else if (d == 1)
ss << "y";
else if (d == 2)
ss << "z";
_vpp_entry_names.push_back(ss.str());
}
}
else
_vpp_entry_names.push_back(_meta_data_types[j]);
}
}

void
SidesetInfoVectorPostprocessor::initialize()
{
for (auto & e : boundaryIDs())
_boundary_data[e] = BoundaryData();

// resize the sideset id vector
_sideset_ids.resize(numBoundaryIDs());

// now we can initialize the _meta_data vector
_meta_data.resize(_vpp_entry_names.size());
for (unsigned int j = 0; j < _vpp_entry_names.size(); ++j)
{
_meta_data[j] = &declareVector(_vpp_entry_names[j]);
_meta_data[j]->resize(numBoundaryIDs());
}
}

void
SidesetInfoVectorPostprocessor::execute()
{
mooseAssert(_boundary_data.find(_current_boundary_id) != _boundary_data.end(),
"_current_boundary_id not found in _boundary_data.");

auto & bd = _boundary_data.find(_current_boundary_id)->second;
bd.area += _current_side_elem->volume();
bd.centroid += _current_side_elem->centroid() * _current_side_elem->volume();

BoundingBox box = _current_side_elem->loose_bounding_box();
Point lmin = box.min();
Point lmax = box.max();

for (unsigned int j = 0; j < 3; ++j)
{
if (lmin(j) < bd.min(j))
bd.min(j) = lmin(j);

if (lmax(j) > bd.max(j))
bd.max(j) = lmax(j);
}
}

void
SidesetInfoVectorPostprocessor::finalize()
{
for (auto & e : _boundary_data)
{
auto & bd = e.second;
gatherSum(bd.area);
for (unsigned int j = 0; j < 3; ++j)
{
gatherMin(bd.min(j));
gatherMax(bd.max(j));
gatherSum(bd.centroid(j));
}
}

// centroid needs to be divided by area
for (auto & e : _boundary_data)
e.second.centroid /= e.second.area;

// fill vectors
unsigned int j = 0;
for (auto & e : _boundary_data)
{
// store away the sideset id first
_sideset_ids[j] = e.first;

// now work through the _vpp_entry_names vector
for (unsigned int i = 0; i < _vpp_entry_names.size(); ++i)
(*_meta_data[i])[j] = dataHelper(e.first, _vpp_entry_names[i]);

// increment counter
++j;
}
}

void
SidesetInfoVectorPostprocessor::threadJoin(const UserObject & y)
{
const SidesetInfoVectorPostprocessor & vpp =
static_cast<const SidesetInfoVectorPostprocessor &>(y);

for (auto & e : _boundary_data)
{
mooseAssert(vpp._boundary_data.find(e.first) != vpp._boundary_data.end(),
"Boundary not found in threadJoin");
auto & vpp_bd = vpp._boundary_data.find(e.first)->second;
auto & bd = e.second;

bd.area += vpp_bd.area;
bd.centroid += vpp_bd.centroid;

for (unsigned int j = 0; j < 3; ++j)
{
if (vpp_bd.min(j) < bd.min(j))
bd.min(j) = vpp_bd.min(j);

if (vpp_bd.max(j) > bd.max(j))
bd.max(j) = vpp_bd.max(j);
}
}
}

Real
SidesetInfoVectorPostprocessor::dataHelper(BoundaryID bid, std::string mdat_tpe) const
{
mooseAssert(_boundary_data.find(bid) != _boundary_data.end(),
"boundary id not found in _boundary_data.");

auto & bd = _boundary_data.find(bid)->second;

if (mdat_tpe == "centroid_x")
return bd.centroid(0);
else if (mdat_tpe == "centroid_y")
return bd.centroid(1);
else if (mdat_tpe == "centroid_z")
return bd.centroid(2);
else if (mdat_tpe == "min_x")
return bd.min(0);
else if (mdat_tpe == "min_y")
return bd.min(1);
else if (mdat_tpe == "min_z")
return bd.min(2);
else if (mdat_tpe == "max_x")
return bd.max(0);
else if (mdat_tpe == "max_y")
return bd.max(1);
else if (mdat_tpe == "max_z")
return bd.max(2);
else if (mdat_tpe == "area")
return bd.area;
else
mooseError("meta_data_type not recognized. This should never happen.");
}
@@ -0,0 +1,4 @@
Boundary IDs,centroid_x,centroid_y,min_x,min_y,max_x,max_y,area
0,0.5,-0.4,0,-0.4,1,-0.4,1
1,1,5,1,-0.4,1,10.4,10.8
3,0,5,0,-0.4,0,10.4,10.8
63 changes: 63 additions & 0 deletions test/tests/vectorpostprocessors/sideset_info/sideset_info.i
@@ -0,0 +1,63 @@
[Mesh]
type = MeshGeneratorMesh

[./uniform]
type = GeneratedMeshGenerator
dim = 2
xmin = 0
xmax = 1
nx = 8
ymin = -0.4
ymax = 10.4
ny = 5
[../]
[]

[Variables]
[./u]
order = FIRST
family = LAGRANGE
[../]
[]

[Kernels]
[./diff]
type = Diffusion
variable = u
[../]
[]

[BCs]
active = 'left right'

[./left]
type = DirichletBC
variable = u
boundary = 1
value = 0
[../]

[./right]
type = DirichletBC
variable = u
boundary = 2
value = 1
[../]
[]

[VectorPostprocessors]
[./side_info]
type = SidesetInfoVectorPostprocessor
boundary = 'left right bottom'
meta_data_types = 'centroid min max area'
[../]
[]

[Executioner]
type = Steady
[]

[Outputs]
file_base = out
csv = true
[]
10 changes: 10 additions & 0 deletions test/tests/vectorpostprocessors/sideset_info/tests
@@ -0,0 +1,10 @@
[Tests]
[./sideset_info]
type = 'CSVDiff'
input = 'sideset_info.i'
csvdiff = 'out_side_info_0001.csv'
issues = '#14275'
design = 'SidesetInfoVectorPostprocessor.md'
requirement = 'The system shall allow outputting relevant information about sidesets'
[../]
[]

0 comments on commit a96ff79

Please sign in to comment.