www.mooseframework.org
PorousFlowFluxLimitedTVDAdvection.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
11 #include "Assembly.h"
12 
14 
15 template <>
16 InputParameters
18 {
19  InputParameters params = validParams<Kernel>();
20  params.addClassDescription("Advective flux of fluid species or heat using "
21  "the Flux Limited TVD scheme invented by Kuzmin and Turek");
22  params.addRequiredParam<UserObjectName>(
23  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
24  params.addRequiredParam<UserObjectName>(
25  "advective_flux_calculator",
26  "PorousFlowAdvectiveFluxCalculator UserObject. This determines whether the advection "
27  "describes a movement of a fluid component in a fluid phase, or movement of heat energy in a "
28  "fluid phase");
29  return params;
30 }
31 
33  const InputParameters & parameters)
34  : Kernel(parameters),
35  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
36  _fluo(getUserObject<PorousFlowAdvectiveFluxCalculatorBase>("advective_flux_calculator"))
37 {
38 }
39 
40 Real
42 {
43  mooseError("PorousFlowFluxLimitedTVDAdvection::computeQpResidual() called\n");
44  return 0.0;
45 }
46 
47 void
49 {
50  prepareVectorTag(_assembly, _var.number());
51  precalculateResidual();
52 
53  // get the residual contributions from _fluo
54  for (unsigned i = 0; i < _current_elem->n_nodes(); ++i)
55  {
56  const dof_id_type node_id_i = _current_elem->node_id(i);
57  _local_re(i) = _fluo.getFluxOut(node_id_i) / _fluo.getValence(node_id_i);
58  }
59 
60  accumulateTaggedLocalResidual();
61 
62  if (_has_save_in)
63  {
64  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
65  for (unsigned int i = 0; i < _save_in.size(); i++)
66  _save_in[i]->sys().solution().add_vector(_local_re, _save_in[i]->dofIndices());
67  }
68 }
69 
70 void
72 {
73  prepareMatrixTag(_assembly, _var.number(), _var.number());
74  precalculateJacobian();
75 
76  // Run through the nodes of this element using "i", getting the Jacobian contributions
77  // d(residual_i)/du(node_j) for all nodes j that can have a nonzero Jacobian contribution. Some
78  // of these node_j will live in this element, but some will live in other elements connected with
79  // node "i", and some will live in the next layer of nodes (eg, in 1D residual_3 could have
80  // contributions from node1, node2, node3, node4 and node5).
81  for (unsigned i = 0; i < _current_elem->n_nodes(); ++i)
82  {
83  // global id of node "i"
84  const dof_id_type node_id_i = _current_elem->node_id(i);
85  // dof number of _var on node "i"
86  std::vector<dof_id_type> idof_indices(
87  1, _current_elem->node_ref(i).dof_number(_sys.number(), _var.number(), 0));
88  // number of times node "i" is encountered in a sweep over elements
89  const unsigned valence = _fluo.getValence(node_id_i);
90 
91  // retrieve the derivative information from _fluo
92  const std::map<dof_id_type, std::vector<Real>> derivs = _fluo.getdFluxOut_dvars(node_id_i);
93 
94  // now build up the dof numbers of all the "j" nodes and the derivative matrix
95  // d(residual_i)/d(var_j)
96  for (unsigned pvar = 0; pvar < _dictator.numVariables(); ++pvar)
97  {
98  const unsigned varnum = _dictator.mooseVariableNum(pvar);
99  std::vector<dof_id_type> jdof_indices(derivs.size());
100  DenseMatrix<Number> deriv_matrix(1, derivs.size());
101  unsigned j = 0;
102  for (const auto & node_j_deriv : derivs)
103  {
104  // global id of j:
105  const dof_id_type node_id_j = node_j_deriv.first;
106  // dof of pvar at node j:
107  jdof_indices[j] = _mesh.getMesh().node_ref(node_id_j).dof_number(_sys.number(), varnum, 0);
108  // derivative must be divided by valence, otherwise the loop over elements will
109  // multiple-count
110  deriv_matrix(0, j) = node_j_deriv.second[pvar] / valence;
111  j++;
112  }
113  // Add the result to the system's Jacobian matrix
114  _assembly.cacheJacobianBlock(deriv_matrix, idof_indices, jdof_indices, _var.scalingFactor());
115  }
116  }
117 }
unsigned getValence(dof_id_type node_i) const
Returns the valence of the global node i Valence is the number of times the node is encountered in a ...
Real getFluxOut(dof_id_type node_i) const
Returns the flux out of lobal node id.
Advection of a quantity with velocity set in the PorousFlowAdvectiveFluxCalculator Depending on the P...
const std::map< dof_id_type, std::vector< Real > > & getdFluxOut_dvars(unsigned node_id) const
Returns d(flux_out)/d(porous_flow_variables.
Base class to compute the advective flux of fluid in PorousFlow situations using the Kuzmin-Turek FEM...
InputParameters validParams< PorousFlowFluxLimitedTVDAdvection >()
unsigned int mooseVariableNum(unsigned int porous_flow_var_num) const
The Moose variable number.
registerMooseObject("PorousFlowApp", PorousFlowFluxLimitedTVDAdvection)
PorousFlowFluxLimitedTVDAdvection(const InputParameters &parameters)
unsigned int numVariables() const
The number of PorousFlow variables.
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
const PorousFlowAdvectiveFluxCalculatorBase & _fluo
The user object that computes Kuzmin and Turek&#39;s K_ij, R+ and R-, etc quantities. ...