Flow123d
concentration_model.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @brief Discontinuous Galerkin method for equation of transport with dispersion.
27  * @author Jan Stebel
28  */
29 
30 #include "input/input_type.hh"
31 #include "mesh/mesh.h"
32 #include "mesh/accessors.hh"
33 #include "flow/darcy_flow_mh.hh"
35 #include "concentration_model.hh"
36 
37 
38 
39 using namespace std;
40 using namespace Input::Type;
41 
42 
43 
44 
45 
46 
47 
49 {
50  ADD_FIELD(bc_conc, "Dirichlet boundary condition (for each substance).", "0.0");
51 
52  ADD_FIELD(init_conc, "Initial concentrations.", "0.0");
53  ADD_FIELD(disp_l, "Longitudal dispersivity (for each substance).", "0.0");
54  ADD_FIELD(disp_t, "Transversal dispersivity (for each substance).", "0.0");
55  ADD_FIELD(diff_m, "Molecular diffusivity (for each substance).", "0.0");
56 
57  output_fields += output_field.name("conc").units("M/L^3");
58 }
59 
60 
61 
62 
63 
64 IT::Record &ConcentrationTransportModel::get_input_type(const string &implementation, const string &description)
65 {
66  static IT::Record rec = IT::Record(ModelEqData::name() + "_" + implementation, description + " for solute transport.")
69  "Names of transported substances.");
70 
71  return rec;
72 }
73 
74 IT::Selection &ConcentrationTransportModel::ModelEqData::get_output_selection_input_type(const string &implementation, const string &description)
75 {
76  static IT::Selection sel = IT::Selection(ModelEqData::name() + "_" + implementation + "_Output", "Output record for " + description + " for solute transport.");
77 
78  return sel;
79 }
80 
81 
83  flux_changed(true)
84 {}
85 
86 
87 void ConcentrationTransportModel::init_data(unsigned int n_subst_)
88 {
89  data().init_conc.n_comp(n_subst_);
90  data().bc_conc.n_comp(n_subst_);
91  data().sources_density.n_comp(n_subst_);
92  data().sources_sigma.n_comp(n_subst_);
93  data().sources_conc.n_comp(n_subst_);
94  data().diff_m.n_comp(n_subst_);
95  data().disp_l.n_comp(n_subst_);
96  data().disp_t.n_comp(n_subst_);
97 }
98 
99 /*
100 void ConcentrationTransportModel::set_cross_section_field(const Field< 3, FieldValue<3>::Scalar >& cross_section)
101 {
102  data().cross_section.copy_from(cross_section);
103 }
104 */
105 
107 {
108  in_rec.val<Input::Array>("substances").copy_to(names);
109 }
110 
111 
113 {
114  return (data().cross_section.changed() || data().porosity.changed());
115 }
116 
117 
119 {
120  return (flux_changed ||
121  data().disp_l.changed() ||
122  data().disp_t.changed() ||
123  data().diff_m.changed() ||
124  data().porosity.changed() ||
126 }
127 
128 
130 {
131  return (flux_changed ||
132  data().bc_conc.changed() ||
133  data().sources_conc.changed() ||
136 }
137 
139  const ElementAccessor<3> &ele_acc,
140  std::vector<double> &mm_coef)
141 {
142  vector<double> elem_csec(point_list.size()), por_m(point_list.size());
143 
144  data().cross_section.value_list(point_list, ele_acc, elem_csec);
145  data().porosity.value_list(point_list, ele_acc, por_m);
146 
147  for (unsigned int i=0; i<point_list.size(); i++)
148  mm_coef[i] = elem_csec[i]*por_m[i];
149 }
150 
151 
153  double Dm, double alphaL, double alphaT, double porosity, double cross_cut, arma::mat33 &K)
154 {
155  double vnorm = arma::norm(velocity, 2);
156 
157  if (fabs(vnorm) > sqrt(numeric_limits<double>::epsilon()))
158  for (int i=0; i<3; i++)
159  for (int j=0; j<3; j++)
160  K(i,j) = velocity[i]*velocity[j]/(vnorm*vnorm)*(alphaL-alphaT) + alphaT*(i==j?1:0);
161  else
162  K.zeros();
163 
164  // Note that the velocity vector is in fact the Darcian flux,
165  // so to obtain |v| we have to divide vnorm by porosity and cross_section.
166  K = (vnorm*K + (Dm*pow(porosity, 1./3)*porosity*cross_cut)*arma::eye(3,3));
167 }
168 
169 
171  const std::vector<arma::vec3> &velocity,
172  const ElementAccessor<3> &ele_acc,
175 {
176  const unsigned int qsize = point_list.size();
177  const unsigned int n_subst = dif_coef.size();
178  std::vector<arma::vec> Dm(qsize), alphaL(qsize), alphaT(qsize);
179  std::vector<double> por_m(qsize), csection(qsize);
180 
181  data().diff_m.value_list(point_list, ele_acc, Dm);
182  data().disp_l.value_list(point_list, ele_acc, alphaL);
183  data().disp_t.value_list(point_list, ele_acc, alphaT);
184  data().porosity.value_list(point_list, ele_acc, por_m);
185  data().cross_section.value_list(point_list, ele_acc, csection);
186 
187  for (unsigned int i=0; i<qsize; i++) {
188  for (int sbi=0; sbi<n_subst; sbi++) {
189  ad_coef[sbi][i] = velocity[i];
190  calculate_dispersivity_tensor(velocity[i], Dm[i][sbi], alphaL[i][sbi], alphaT[i][sbi], por_m[i], csection[i], dif_coef[sbi][i]);
191  }
192  }
193 }
194 
195 
197  const ElementAccessor<3> &ele_acc,
198  std::vector< arma::vec > &init_values)
199 {
200  data().init_conc.value_list(point_list, ele_acc, init_values);
201 }
202 
203 
205  const ElementAccessor<3> &ele_acc,
206  std::vector< arma::vec > &bc_values)
207 {
208  data().bc_conc.value_list(point_list, ele_acc, bc_values);
209 }
210 
211 
213  const ElementAccessor<3> &ele_acc,
214  std::vector<arma::vec> &sources_value,
215  std::vector<arma::vec> &sources_density,
216  std::vector<arma::vec> &sources_sigma)
217 {
218  const unsigned int qsize = point_list.size();
219  vector<double> csection(qsize);
220  data().cross_section.value_list(point_list, ele_acc, csection);
221  data().sources_conc.value_list(point_list, ele_acc, sources_value);
222  data().sources_density.value_list(point_list, ele_acc, sources_density);
223  data().sources_sigma.value_list(point_list, ele_acc, sources_sigma);
224 
225  for (unsigned int k=0; k<qsize; k++)
226  {
227  sources_density[k] *= csection[k];
228  sources_sigma[k] *= csection[k];
229  }
230 }
231 
232 
234  const ElementAccessor<3> &ele_acc,
235  std::vector<arma::vec> &sources_sigma)
236 {
237  const unsigned int qsize = point_list.size();
238  vector<double> csection(qsize);
239  data().cross_section.value_list(point_list, ele_acc, csection);
240  data().sources_sigma.value_list(point_list, ele_acc, sources_sigma);
241 
242  for (unsigned int k=0; k<qsize; k++)
243  sources_sigma[k] *= csection[k];
244 }
245 
246 
248 {}
249 
250 
251