Flow123d  release_1.8.2-1603-g0109a2b
concentration_model.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file concentration_model.cc
15  * @brief Discontinuous Galerkin method for equation of transport with dispersion.
16  * @author Jan Stebel
17  */
18 
19 #include "input/input_type.hh"
20 #include "mesh/mesh.h"
21 #include "mesh/accessors.hh"
22 //#include "flow/darcy_flow_mh.hh"
23 
25 #include "concentration_model.hh"
26 #include "fields/unit_si.hh"
27 #include "coupling/balance.hh"
28 
29 
30 
31 using namespace std;
32 using namespace Input::Type;
33 
34 
35 
37  return Selection("ConvectionDiffusion_BC_Type", "Types of boundary conditions for solute transport model.")
38  .add_value(bc_inflow, "inflow",
39  "Default transport boundary condition.\n"
40  "On water inflow (($(q_w \\le 0)$)), total flux is given by the reference concentration 'bc_conc'. "
41  "On water outflow we prescribe zero diffusive flux, "
42  "i.e. the mass flows out only due to advection.")
43  .add_value(bc_dirichlet, "dirichlet",
44  "Dirichlet boundary condition (($ c = c_D $)).\n"
45  "The prescribed concentration (($c_D$)) is specified by the field 'bc_conc'.")
46  .add_value(bc_total_flux, "total_flux",
47  "Total mass flux boundary condition.\n"
48  "The prescribed total incoming flux can have the general form (($\\delta(f_N+\\sigma_R(c_R-c) )$)), "
49  "where the absolute flux (($f_N$)) is specified by the field 'bc_flux', "
50  "the transition parameter (($\\sigma_R$)) by 'bc_robin_sigma', "
51  "and the reference concentration (($c_R$)) by 'bc_conc'.")
52  .add_value(bc_diffusive_flux, "diffusive_flux",
53  "Diffusive flux boundary condition.\n"
54  "The prescribed incoming mass flux due to diffusion can have the general form (($\\delta(f_N+\\sigma_R(c_R-c) )$)), "
55  "where the absolute flux (($f_N$)) is specified by the field 'bc_flux', "
56  "the transition parameter (($\\sigma_R$)) by 'bc_robin_sigma', "
57  "and the reference concentration (($c_R$)) by 'bc_conc'.")
58  .close();
59 }
60 
61 
62 
63 
66 {
67  *this+=bc_type
68  .name("bc_type")
69  .description(
70  "Type of boundary condition.")
72  .input_default("\"inflow\"")
75  *this+=bc_dirichlet_value
76  .name("bc_conc")
77  .units( UnitSI().kg().m(-3) )
78  .description("Dirichlet boundary condition (for each substance).")
79  .input_default("0.0")
80  .flags_add( in_rhs );
81  *this+=bc_flux
83  .name("bc_flux")
84  .description("Flux in Neumann boundary condition.")
85  .units( UnitSI().kg().m().s(-1).md() )
86  .input_default("0.0")
87  .flags_add(FieldFlag::in_rhs);
88  *this+=bc_robin_sigma
90  .name("bc_robin_sigma")
91  .description("Conductivity coefficient in Robin boundary condition.")
92  .units( UnitSI().m(4).s(-1).md() )
93  .input_default("0.0")
94  .flags_add(FieldFlag::in_rhs & FieldFlag::in_main_matrix);
95  *this+=init_conc
96  .name("init_conc")
97  .units( UnitSI().kg().m(-3) )
98  .description("Initial concentrations.")
99  .input_default("0.0");
100  *this+=disp_l
101  .name("disp_l")
102  .description("Longitudal dispersivity (for each substance).")
103  .units( UnitSI().m() )
104  .input_default("0.0")
106  *this+=disp_t
107  .name("disp_t")
108  .description("Transversal dispersivity (for each substance).")
109  .units( UnitSI().m() )
110  .input_default("0.0")
111  .flags_add( in_main_matrix & in_rhs );
112  *this+=diff_m
113  .name("diff_m")
114  .description("Molecular diffusivity (for each substance).")
115  .units( UnitSI().m(2).s(-1) )
116  .input_default("0.0")
117  .flags_add( in_main_matrix & in_rhs );
118 
119  *this+=output_field
120  .name("conc")
121  .units( UnitSI().kg().m(-3) )
123 }
124 
125 
126 
127 IT::Record ConcentrationTransportModel::get_input_type(const string &implementation, const string &description)
128 {
129  return IT::Record(
130  std::string(ModelEqData::name()) + "_" + implementation,
131  description + " for solute transport.")
133 }
134 
136 {
137  // Return empty selection just to provide model specific selection name and description.
138  // The fields are added by TransportDG using an auxiliary selection.
139  return IT::Selection(
140  std::string(ModelEqData::name()) + "_DG_output_fields",
141  "Selection of output fields for Diffusive Solute Transport DG model.");
142 }
143 
144 
146  ConcentrationTransportBase(mesh, in_rec),
147  flux_changed(true),
148  mh_dh(nullptr)
149 {}
150 
151 
153 {
154  substances.initialize(in_rec.val<Input::Array>("substances"));
155 }
156 
157 
159  const ElementAccessor<3> &ele_acc,
160  std::vector<double> &mm_coef)
161 {
162  vector<double> elem_csec(point_list.size()), por_m(point_list.size());
163 
164  data().cross_section.value_list(point_list, ele_acc, elem_csec);
165  data().porosity.value_list(point_list, ele_acc, por_m);
166 
167  for (unsigned int i=0; i<point_list.size(); i++)
168  mm_coef[i] = elem_csec[i]*por_m[i];
169 }
170 
171 
173  double Dm, double alphaL, double alphaT, double porosity, double cross_cut, arma::mat33 &K)
174 {
175  double vnorm = arma::norm(velocity, 2);
176 
177  if (fabs(vnorm) > 0)
178  for (int i=0; i<3; i++)
179  for (int j=0; j<3; j++)
180  K(i,j) = (velocity[i]/vnorm)*(velocity[j]/vnorm)*(alphaL-alphaT) + alphaT*(i==j?1:0);
181  else
182  K.zeros();
183 
184  // Note that the velocity vector is in fact the Darcian flux,
185  // so to obtain |v| we have to divide vnorm by porosity and cross_section.
186  K = (vnorm*K + (Dm*pow(porosity, 1./3)*porosity*cross_cut)*arma::eye(3,3));
187 }
188 
189 
190 
191 
193  const std::vector<arma::vec3> &velocity,
194  const ElementAccessor<3> &ele_acc,
197 {
198  const unsigned int qsize = point_list.size();
199  const unsigned int n_subst = dif_coef.size();
200  std::vector<arma::vec> Dm(qsize, arma::vec(n_subst) ), alphaL(qsize, arma::vec(n_subst) ), alphaT(qsize, arma::vec(n_subst) );
201  std::vector<double> por_m(qsize), csection(qsize);
202 
203  data().diff_m.value_list(point_list, ele_acc, Dm);
204  data().disp_l.value_list(point_list, ele_acc, alphaL);
205  data().disp_t.value_list(point_list, ele_acc, alphaT);
206  data().porosity.value_list(point_list, ele_acc, por_m);
207  data().cross_section.value_list(point_list, ele_acc, csection);
208 
209  for (unsigned int i=0; i<qsize; i++) {
210  for (unsigned int sbi=0; sbi<n_subst; sbi++) {
211  ad_coef[sbi][i] = velocity[i];
212  calculate_dispersivity_tensor(velocity[i],
213  Dm[i][sbi], alphaL[i][sbi], alphaT[i][sbi], por_m[i], csection[i],
214  dif_coef[sbi][i]);
215  }
216  }
217 }
218 
219 
221  const ElementAccessor<3> &ele_acc,
222  std::vector< arma::vec > &init_values)
223 {
224  data().init_conc.value_list(point_list, ele_acc, init_values);
225 }
226 
228  arma::uvec &bc_types)
229 {
230  // Currently the bc types for ConcentrationTransport are numbered in the same way as in TransportDG.
231  // In general we should use some map here.
232  bc_types = data().bc_type.value(ele_acc.centre(), ele_acc);
233 }
234 
235 
237  const std::vector<arma::vec3> &point_list,
238  const ElementAccessor<3> &ele_acc,
239  std::vector< double > &bc_flux,
240  std::vector< double > &bc_sigma,
241  std::vector< double > &bc_ref_value)
242 {
243  data().bc_flux[index].value_list(point_list, ele_acc, bc_flux);
244  data().bc_robin_sigma[index].value_list(point_list, ele_acc, bc_sigma);
245  data().bc_dirichlet_value[index].value_list(point_list, ele_acc, bc_ref_value);
246 
247  // Change sign in bc_flux since internally we work with outgoing fluxes.
248  for (auto f : bc_flux) f = -f;
249 }
250 
252  const std::vector<arma::vec3> &point_list,
253  const ElementAccessor<3> &ele_acc,
254  std::vector< double > &bc_sigma)
255 {
256  data().bc_robin_sigma[index].value_list(point_list, ele_acc, bc_sigma);
257 }
258 
259 
261  const ElementAccessor<3> &ele_acc,
262  std::vector<arma::vec> &sources_value,
263  std::vector<arma::vec> &sources_density,
264  std::vector<arma::vec> &sources_sigma)
265 {
266  const unsigned int qsize = point_list.size();
267  vector<double> csection(qsize);
268  data().cross_section.value_list(point_list, ele_acc, csection);
269  data().sources_conc.value_list(point_list, ele_acc, sources_value);
270  data().sources_density.value_list(point_list, ele_acc, sources_density);
271  data().sources_sigma.value_list(point_list, ele_acc, sources_sigma);
272 
273  for (unsigned int k=0; k<qsize; k++)
274  {
275  sources_density[k] *= csection[k];
276  sources_sigma[k] *= csection[k];
277  }
278 }
279 
280 
282  const ElementAccessor<3> &ele_acc,
283  std::vector<arma::vec> &sources_sigma)
284 {
285  const unsigned int qsize = point_list.size();
286  vector<double> csection(qsize);
287  data().cross_section.value_list(point_list, ele_acc, csection);
288  data().sources_sigma.value_list(point_list, ele_acc, sources_sigma);
289 
290  for (unsigned int k=0; k<qsize; k++)
291  sources_sigma[k] *= csection[k];
292 }
293 
294 
296 {}
297 
298 
299 void ConcentrationTransportModel::set_balance_object(boost::shared_ptr<Balance> balance)
300 {
301  balance_ = balance;
302  subst_idx = balance_->add_quantities(substances_.names());
303 }
304 
305 
306 
void get_bc_type(const ElementAccessor< 3 > &ele_acc, arma::uvec &bc_types) override
SubstanceList substances_
Transported substances.
static const Input::Type::Selection & get_bc_type_selection()
ConcentrationTransportModel(Mesh &mesh, const Input::Record &in_rec)
MultiField< 3, FieldValue< 3 >::Scalar > output_field
Accessor to input data conforming to declared Array.
Definition: accessors.hh:552
auto disable_where(const MultiField< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> MultiField &
static constexpr Mask in_main_matrix
A field is part of main "stiffness matrix" of the equation.
Definition: field_flag.hh:44
MultiField< 3, FieldValue< 3 >::Scalar > init_conc
Initial concentrations.
const std::vector< std::string > & names()
Definition: substance.hh:85
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
SubstanceList & substances() override
Returns reference to the vector of substance names.
MultiField< 3, FieldValue< 3 >::Scalar > diff_m
Molecular diffusivity (for each substance).
void initialize(const Input::Array &in_array)
Read from input array.
Definition: substance.cc:58
void get_flux_bc_data(unsigned int index, const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< double > &bc_flux, std::vector< double > &bc_sigma, std::vector< double > &bc_ref_value) override
Return data for diffusive or total flux b.c.
MultiField< 3, FieldValue< 3 >::Scalar > sources_density
Concentration sources - density of substance source, only positive part is used.
Definition: mesh.h:99
MultiField< 3, FieldValue< 3 >::Scalar > sources_conc
bool flux_changed
Indicator of change in advection vector field.
static constexpr const char * name()
void compute_mass_matrix_coefficient(const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< double > &mm_coef) override
static Input::Type::Abstract & get_input_type()
Common specification of the input record for secondary equations.
Discontinuous Galerkin method for equation of transport with dispersion.
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) const
Definition: field.hh:351
void set_components(SubstanceList &substances, const Input::Record &in_rec) override
Read or set names of solution components.
MultiField< 3, FieldValue< 3 >::Scalar > disp_t
Transversal dispersivity (for each substance).
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:193
BCMultiField< 3, FieldValue< 3 >::Enum > bc_type
Type of boundary condition (see also BC_Type)
BCMultiField< 3, FieldValue< 3 >::Scalar > bc_dirichlet_value
Prescribed concentration for Dirichlet/reference concentration for flux b.c.
void compute_init_cond(const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< arma::vec > &init_values) override
void compute_sources_sigma(const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< arma::vec > &sources_sigma) override
static constexpr Mask equation_result
Match result fields. These are never given by input or copy of input.
Definition: field_flag.hh:49
Mesh & mesh()
Definition: equation.hh:174
FieldCommon & input_default(const string &input_default)
MultiField< 3, FieldValue< 3 >::Scalar > sources_sigma
Concentration sources - Robin type, in_flux = sources_sigma * (sources_conc - mobile_conc) ...
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Adds one new value with name given by key to the Selection.
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
FieldCommon & input_selection(const Input::Type::Selection *element_selection)
void calculate_dispersivity_tensor(const arma::vec3 &velocity, double Dm, double alphaL, double alphaT, double porosity, double cross_cut, arma::mat33 &K)
const Ret val(const string &key) const
Field< 3, FieldValue< 3 >::Scalar > porosity
Mobile porosity.
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
Definition: field_flag.hh:46
BCMultiField< 3, FieldValue< 3 >::Scalar > bc_robin_sigma
Transition coefficient in total/diffusive flux b.c.
void compute_source_coefficients(const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< arma::vec > &sources_conc, std::vector< arma::vec > &sources_density, std::vector< arma::vec > &sources_sigma) override
void set_balance_object(boost::shared_ptr< Balance > balance) override
FieldCommon & description(const string &description)
Definition: field_common.hh:90
MultiField< 3, FieldValue< 3 >::Scalar > disp_l
Longitudal dispersivity (for each substance).
void get_flux_bc_sigma(unsigned int index, const std::vector< arma::vec3 > &point_list, const ElementAccessor< 3 > &ele_acc, std::vector< double > &bc_sigma) override
Return transition coefficient for flux b.c.
virtual MultiFieldValue::return_type value(const Point &p, const ElementAccessor< spacedim > &elm) const
const Selection & close() const
Close the Selection, no more values can be added.
BCMultiField< 3, FieldValue< 3 >::Scalar > bc_flux
Flux value in total/diffusive flux b.c.
FieldCommon & name(const string &name)
Definition: field_common.hh:83
vector< unsigned int > subst_idx
List of indices used to call balance methods for a set of quantities.
arma::vec::fixed< spacedim > centre() const
Definition: accessors.hh:91
boost::shared_ptr< Balance > balance_
object for calculation and writing the mass balance to file.
Definition: equation.hh:233
Record type proxy class.
Definition: type_record.hh:171
FieldCommon & flags(FieldFlag::Flags::Mask mask)
Field< 3, FieldValue< 3 >::Scalar > cross_section
Pointer to DarcyFlow field cross_section.
Class for representation SI units of Fields.
Definition: unit_si.hh:40
void compute_advection_diffusion_coefficients(const std::vector< arma::vec3 > &point_list, const std::vector< arma::vec3 > &velocity, const ElementAccessor< 3 > &ele_acc, std::vector< std::vector< arma::vec3 > > &ad_coef, std::vector< std::vector< arma::mat33 > > &dif_coef) override
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:53
virtual ModelEqData & data()=0
Derived class should implement getter for ModelEqData instance.
Template for classes storing finite set of named values.
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename MultiFieldValue::return_type > &value_list) const