https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowMaterial.C
Go to the documentation of this file.
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 "PorousFlowMaterial.h"
11
13
14#include "libmesh/quadrature.h"
15
16#include <limits>
17
20{
22 params.addRequiredParam<UserObjectName>(
23 "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
24 params.addParam<bool>(
25 "at_nodes", false, "Evaluate Material properties at nodes instead of quadpoints");
26 params.addPrivateParam<std::string>("pf_material_type", "pf_material");
27 params.addClassDescription("This generalises MOOSE's Material class to allow for Materials that "
28 "hold information related to the nodes in the finite element");
29
30 // Needed due to the custom tomfoolery going on with nodal material sizing in
31 // initStatefulProperties()
32 params.set<bool>("_force_stateful_init") = true;
33
34 return params;
35}
36
38 : Material(parameters),
39 _nodal_material(getParam<bool>("at_nodes")),
40 _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
41 _pressure_variable_name("pressure_variable"),
42 _saturation_variable_name("saturation_variable"),
43 _temperature_variable_name("temperature_variable"),
44 _mass_fraction_variable_name("mass_fraction_variable")
45{
46}
47
48void
50{
51 if (!_nodal_material)
52 return;
53
56 if (!storage.hasStatefulProperties())
57 return;
58
59 auto & stateful_prop_id_to_prop_id = storage.statefulProps();
60 for (const auto i : index_range(stateful_prop_id_to_prop_id))
61 {
62 const auto prop_id = stateful_prop_id_to_prop_id[i];
63 if (_supplied_prop_ids.count(prop_id))
64 _supplied_old_prop_ids.push_back(i);
65 }
66}
67
68void
70{
72 {
73 // size the properties to max(number_of_nodes, number_of_quadpoints)
75
76 // compute the values for number_of_nodes
78 }
79 else
81}
82
83void
85{
86 const unsigned int numnodes = _current_elem->n_nodes();
87
88 // compute the values for all nodes
89 for (_qp = 0; _qp < numnodes; ++_qp)
91
92 // If number_of_nodes < number_of_quadpoints, the remaining values in the
93 // material data array are zero (for scalars) and empty (for vectors).
94 // Unfortunately, this can cause issues with adaptivity, where the empty
95 // value can be transferred to a node in a child element. This can lead
96 // to a segfault when accessing stateful properties, see #14428.
97 // To prevent this, we copy the last node value to the empty array positions.
98 if (numnodes < _qrule->n_points())
99 {
101
102 // Copy from qp = _current_elem->n_nodes() - 1 to qp = _qrule->n_points() -1
103 for (const auto & prop_id : _supplied_prop_ids)
104 for (unsigned int qp = numnodes; qp < _qrule->n_points(); ++qp)
105 props[prop_id].qpCopy(qp, props[prop_id], numnodes - 1);
106 }
107}
108
109void
111{
112 if (_nodal_material)
113 {
114 // size the properties to max(number_of_nodes, number_of_quadpoints)
116
118 }
119 else
121}
122
123void
125{
126 /*
127 * For nodal materials, the Properties should be sized as the maximum of
128 * the number of nodes and the number of quadpoints.
129 * We only actually need "number of nodes" pieces of information, which are
130 * computed by computeProperties(), so the n_points - _current_elem->n_nodes()
131 * elements at the end of the std::vector will always be zero, but they
132 * are needed because MOOSE does copy operations (etc) that assumes that
133 * the std::vector is sized to number of quadpoints.
134 *
135 * On boundary materials, the number of nodes may be larger than the number of
136 * qps on the face of the element, in which case the remaining entries in the
137 * material properties storage will be zero.
138 *
139 * \author lindsayad: MooseArray currently has the unfortunate side effect that if your new size
140 * is greater than the current size, then we clear the whole data structure. Consequently this
141 * call has the potential to clear material property evaluations done earlier in the material
142 * dependency chain. So instead we selectively resize just our own properties and not everyone's
143 */
144 // _material_data.resize(std::max(_current_elem->n_nodes(), _qrule->n_points()));
145
146 const auto new_size = std::max(_current_elem->n_nodes(), _qrule->n_points());
148
149 auto & props = _material_data.props();
150 for (const auto prop_id : _supplied_prop_ids)
151 props[prop_id].resize(new_size);
152
153 for (const auto state : storage.statefulIndexRange())
154 for (const auto prop_id : _supplied_old_prop_ids)
155 if (_material_data.props(state).hasValue(prop_id))
156 _material_data.props(state)[prop_id].resize(new_size);
157}
158
159unsigned
160PorousFlowMaterial::nearestQP(unsigned nodenum) const
161{
162 unsigned nearest_qp = 0;
163 Real smallest_dist = std::numeric_limits<Real>::max();
164 for (const auto qp : make_range(_qrule->n_points()))
165 {
166 const Real this_dist = (_current_elem->point(nodenum) - _q_point[qp]).norm();
167 if (this_dist < smallest_dist)
168 {
169 nearest_qp = qp;
170 smallest_dist = this_dist;
171 }
172 }
173 return nearest_qp;
174}
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addPrivateParam(const std::string &name, const T &value)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
virtual void computeQpProperties()
virtual void initStatefulProperties(const unsigned int n_points)
unsigned int _qp
std::set< unsigned int > _supplied_prop_ids
void onlyResizeIfSmaller(bool flag)
const MaterialPropertyStorage & getMaterialPropertyStorage() const
const MaterialProperties & props(const unsigned int state=0) const
void resize(const std::size_t size, const WriteKey)
MaterialData & _material_data
const std::vector< unsigned int > & statefulProps() const
virtual void computeProperties() override
static InputParameters validParams()
const Elem *const & _current_elem
const QBase *const & _qrule
const MooseArray< Point > & _q_point
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
std::vector< unsigned int > _supplied_old_prop_ids
stateful material property ids that this material supplies
virtual void initStatefulProperties(unsigned int n_points) override
Correctly sizes nodal materials, then initialises using Material::initStatefulProperties.
static InputParameters validParams()
virtual void initialSetup() override
virtual void computeProperties() override
Correctly sizes nodal materials, then computes using Material::computeProperties.
unsigned nearestQP(unsigned nodenum) const
Find the nearest quadpoint to the node labelled by nodenum in the current element.
void computeNodalProperties()
Compute the material properties at each node, and if the number of nodes is less than the number of q...
void sizeNodalProperties()
Resizes properties to be equal to max(number of nodes, number of quadpoints) in the current element.
PorousFlowMaterial(const InputParameters &parameters)
const bool _nodal_material
Whether the derived class holds nodal values.
bool hasValue(const std::size_t i) const