Flow123d  jenkins-Flow123d-windows-release-multijob-285
transport.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  *
17  * You should have received a copy of the GNU General Public License along with this program; if not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
19  *
20  *
21  * $Id$
22  * $Revision$
23  * $LastChangedBy$
24  * $LastChangedDate$
25  *
26  * @file
27  * @ingroup transport
28  * @brief Transport
29  *
30  *
31  */
32 
33 
34 #include <memory>
35 
36 #include "system/system.hh"
37 #include "system/sys_profiler.hh"
38 
39 #include "mesh/mesh.h"
40 #include "mesh/partitioning.hh"
41 #include "transport/transport.h"
42 
43 #include "la/distribution.hh"
44 
45 #include "la/sparse_graph.hh"
46 #include <iostream>
47 #include <iomanip>
48 #include <string>
49 
50 #include "io/output_time.hh"
51 #include "tools/time_governor.hh"
52 // TODO: move partitioning into mesh_ and remove this include
53 //#include "flow/darcy_flow_mh.hh"
54 #include "flow/old_bcd.hh"
55 #include "input/accessors.hh"
56 #include "input/input_type.hh"
57 
59 #include "fields/field_values.hh"
61 #include "fields/generic_field.hh"
62 
63 #include "reaction/isotherm.hh" // SorptionType enum
64 
65 namespace IT = Input::Type;
66 
67 
69  .add_value(Isotherm::none,"none","No sorption considered")
70  .add_value(Isotherm::linear,"linear","Linear isotherm described sorption considered.")
71  .add_value(Isotherm::freundlich,"freundlich","Freundlich isotherm described sorption considered")
72  .add_value(Isotherm::langmuir,"langmuir","Langmuir isotherm described sorption considered")
73  .close();
74 
75 
77  EqData().output_fields.make_output_field_selection("ConvectionTransport_Output")
78  .close();
79 
80 
82 {
83  ADD_FIELD(bc_conc, "Boundary conditions for concentrations.", "0.0");
84  bc_conc.add_factory( OldBcdInput::instance()->trans_conc_factory );
85  bc_conc.units( UnitSI().kg().m(-3) );
86  ADD_FIELD(init_conc, "Initial concentrations.", "0.0");
87  init_conc.units( UnitSI().kg().m(-3) );
88 
89  output_fields += *this;
90  output_fields += conc_mobile.name("conc").units( UnitSI().kg().m(-3) );
91  output_fields += region_id.name("region_id")
94 }
95 
96 
98 : TransportBase(init_mesh, in_rec)
99 {
100  START_TIMER("ConvectionTransport");
101  this->eq_data_ = &data_;
102 
103  //mark type of the equation of convection transport (created in EquationBase constructor) and it is fixed
104  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"));
106 
108 
109  // Initialize list of substances.
110  substances_.initialize(in_rec.val<Input::Array>("substances"));
112  INPUT_CHECK(n_subst_ >= 1 ,"Number of substances must be positive.\n");
113 
115  data_.set_mesh(init_mesh);
116  data_.set_input_list( in_rec.val<Input::Array>("input_fields") );
118 
122  transport_matrix_time = -1.0; // or -infty
124  need_time_rescaling=true;
125 
126  // register output vectors
127  output_rec = in_rec.val<Input::Record>("output_stream");
134  for (unsigned int sbi=0; sbi<n_subst_; sbi++)
135  {
136  // create shared pointer to a FieldElementwise and push this Field to output_field on all regions
137  auto output_field_ptr = out_conc[sbi].create_field<3, FieldValue<3>::Scalar>(n_subst_);
138  data_.conc_mobile[sbi].set_field(mesh_->region_db().get_region_set("ALL"), output_field_ptr, 0);
139  }
141  output_stream_->add_admissible_field_names(in_rec.val<Input::Array>("output_fields"));
143 
144  // initialization of balance object
146  if (it->val<bool>("balance_on"))
147  {
148  balance_ = boost::make_shared<Balance>("mass", mesh_, el_ds, el_4_loc, *it);
149 
150  subst_idx = balance_->add_quantities(substances_.names());
151 
152  balance_->allocate(el_ds->lsize(), 1);
153  }
154 
155 }
156 
157 
158 //=============================================================================
159 // MAKE TRANSPORT
160 //=============================================================================
162 
163  int * id_4_old = new int[mesh_->n_elements()];
164  int i = 0;
165  FOR_ELEMENTS(mesh_, ele) id_4_old[i++] = ele.index();
167  delete[] id_4_old;
168 
169  // TODO: make output of partitioning is usefull but makes outputs different
170  // on different number of processors, which breaks tests.
171  //
172  // Possible solution:
173  // - have flag in ini file to turn this output ON
174  // - possibility to have different ref_output for different num of proc.
175  // - or do not test such kind of output
176  //
177  //FOR_ELEMENTS(mesh_, ele) {
178  // ele->pid=el_ds->get_proc(row_4_el[ele.index()]);
179  //}
180 
181 }
182 
183 
184 
186 {
187  unsigned int sbi;
188 
189  //Destroy mpi vectors at first
190  VecDestroy(&v_sources_corr);
191  MatDestroy(&tm);
192 
193  VecDestroy(vconc);
194  VecDestroy(bcvcorr);
195  VecDestroy(vpconc);
196  VecDestroy(vcumulative_corr);
197 
198  for (sbi = 0; sbi < n_subst_; sbi++) {
199  //no mpi vectors
200  xfree(sources_density[sbi]);
201  xfree(sources_conc[sbi]);
202  xfree(sources_sigma[sbi]);
203  xfree(cumulative_corr[sbi]);
204  }
205 
206 
208 
213 
214  delete output_stream_;
215 
216 }
217 
218 
219 
220 
221 
223 {
224  FOR_ELEMENTS(mesh_, elem)
225  {
226  if (!el_ds->is_local(row_4_el[elem.index()])) continue;
227 
228  unsigned int index = row_4_el[elem.index()] - el_ds->begin();
229  ElementAccessor<3> ele_acc = mesh_->element_accessor(elem.index());
230  arma::vec value = data_.init_conc.value(elem->centre(), ele_acc);
231 
232  for (unsigned int sbi=0; sbi<n_subst_; sbi++)
233  conc[sbi][index] = value(sbi);
234  }
235 
236 }
237 
238 //=============================================================================
239 // ALLOCATE OF TRANSPORT VARIABLES (ELEMENT & NODES)
240 //=============================================================================
242 
243  unsigned int i;
244  int sbi, n_subst;
245  n_subst = n_subst_;
246 
247 
248  sources_corr = new double[el_ds->lsize()];
249  sources_density = (double**) xmalloc(n_subst * sizeof(double*));
250  sources_conc = (double**) xmalloc(n_subst * sizeof(double*));
251  sources_sigma = (double**) xmalloc(n_subst * sizeof(double*));
252 
253  cumulative_corr = (double**) xmalloc(n_subst * sizeof(double*));
254  for (sbi = 0; sbi < n_subst; sbi++) {
255  sources_density[sbi] = (double*) xmalloc(el_ds->lsize() * sizeof(double));
256  sources_conc[sbi] = (double*) xmalloc(el_ds->lsize() * sizeof(double));
257  sources_sigma[sbi] = (double*) xmalloc(el_ds->lsize() * sizeof(double));
258  cumulative_corr[sbi] = (double*) xmalloc(el_ds->lsize() * sizeof(double));
259  }
260 
261  conc = (double**) xmalloc(n_subst * sizeof(double*));
262  out_conc.clear();
263  out_conc.resize(n_subst);
264  for (sbi = 0; sbi < n_subst; sbi++) {
265  conc[sbi] = (double*) xmalloc(el_ds->lsize() * sizeof(double));
266  out_conc[sbi].resize( el_ds->size() );
267  for (i = 0; i < el_ds->lsize(); i++) {
268  conc[sbi][i] = 0.0;
269  }
270  }
271 }
272 
273 //=============================================================================
274 // ALLOCATION OF TRANSPORT VECTORS (MPI)
275 //=============================================================================
277 
278  int sbi, n_subst, rank, np;
279  n_subst = n_subst_;
280 
281  MPI_Barrier(PETSC_COMM_WORLD);
282  MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
283  MPI_Comm_size(PETSC_COMM_WORLD, &np);
284 
285  bcvcorr = (Vec*) xmalloc(n_subst * (sizeof(Vec)));
286  vconc = (Vec*) xmalloc(n_subst * (sizeof(Vec)));
287  vpconc = (Vec*) xmalloc(n_subst * (sizeof(Vec)));
288  vcumulative_corr = (Vec*) xmalloc(n_subst * (sizeof(Vec)));
289 
290 
291  VecCreateMPIWithArray(PETSC_COMM_WORLD,1, el_ds->lsize(), PETSC_DECIDE,
293 
294  for (sbi = 0; sbi < n_subst; sbi++) {
295  VecCreateMPI(PETSC_COMM_WORLD, el_ds->lsize(), mesh_->n_elements(), &bcvcorr[sbi]);
296  VecZeroEntries(bcvcorr[sbi]);
297  VecCreateMPIWithArray(PETSC_COMM_WORLD,1, el_ds->lsize(), mesh_->n_elements(), conc[sbi],
298  &vconc[sbi]);
299 
300  VecCreateMPI(PETSC_COMM_WORLD, el_ds->lsize(), mesh_->n_elements(), &vpconc[sbi]);
301  VecZeroEntries(vconc[sbi]);
302  VecZeroEntries(vpconc[sbi]);
303 
304  // SOURCES
305  VecCreateMPIWithArray(PETSC_COMM_WORLD,1, el_ds->lsize(), mesh_->n_elements(),
306  cumulative_corr[sbi],&vcumulative_corr[sbi]);
307 
308  VecZeroEntries(vcumulative_corr[sbi]);
309  VecZeroEntries(out_conc[sbi].get_data_petsc());
310  }
311 
312 
313  MatCreateAIJ(PETSC_COMM_WORLD, el_ds->lsize(), el_ds->lsize(), mesh_->n_elements(),
314  mesh_->n_elements(), 16, PETSC_NULL, 4, PETSC_NULL, &tm);
315 
316 }
317 
318 
320 {
321  START_TIMER ("set_boundary_conditions");
322 
324 
325  unsigned int sbi, loc_el, loc_b = 0;
326 
327  // Assembly bcvcorr vector
328  for(sbi=0; sbi < n_subst_; sbi++) VecZeroEntries(bcvcorr[sbi]);
329 
330  if (balance_ != nullptr)
331  balance_->start_flux_assembly(subst_idx);
332 
333  for (loc_el = 0; loc_el < el_ds->lsize(); loc_el++) {
334  elm = mesh_->element(el_4_loc[loc_el]);
335  if (elm->boundary_idx_ != NULL) {
336  unsigned int new_i = row_4_el[elm.index()];
337  double csection = data_.cross_section.value(elm->centre(), elm->element_accessor());
338  double por_m = data_.porosity.value(elm->centre(), elm->element_accessor());
339 
340  FOR_ELEMENT_SIDES(elm,si) {
341  Boundary *b = elm->side(si)->cond();
342  if (b != NULL) {
343  double flux = mh_dh->side_flux( *(elm->side(si)) );
344  if (flux < 0.0) {
345  double aij = -(flux / (elm->measure() * csection * por_m) );
346 
347  arma::vec value = data_.bc_conc.value( b->element()->centre(), b->element_accessor() );
348  for (sbi=0; sbi<n_subst_; sbi++)
349  VecSetValue(bcvcorr[sbi], new_i, value[sbi] * aij, ADD_VALUES);
350 
351  if (balance_ != nullptr)
352  {
353  for (unsigned int sbi=0; sbi<n_substances(); sbi++)
354  {
355  balance_->add_flux_matrix_values(subst_idx[sbi], loc_b, {row_4_el[el_4_loc[loc_el]]}, {0.});
356  balance_->add_flux_vec_value(subst_idx[sbi], loc_b, flux*value[sbi]);
357  }
358  }
359  } else {
360  if (balance_ != nullptr)
361  {
362  for (unsigned int sbi=0; sbi<n_substances(); sbi++)
363  {
364  balance_->add_flux_matrix_values(subst_idx[sbi], loc_b, {row_4_el[el_4_loc[loc_el]]}, {flux});
365  }
366  }
367  }
368  ++loc_b;
369  }
370  }
371 
372  }
373  }
374 
375  if (balance_ != nullptr)
376  balance_->finish_flux_assembly(subst_idx);
377 
378  for (sbi=0; sbi<n_subst_; sbi++) VecAssemblyBegin(bcvcorr[sbi]);
379  for (sbi=0; sbi<n_subst_; sbi++) VecAssemblyEnd(bcvcorr[sbi]);
380 
381 }
382 
383 
384 //=============================================================================
385 // COMPUTE SOURCES
386 //=============================================================================
388 
389  //temporary variables
390  unsigned int loc_el;
391  double conc_diff, csection, por_m;
392  ElementAccessor<3> ele_acc;
393  arma::vec3 p;
394 
395  //TODO: would it be possible to check the change in data for chosen substance? (may be in multifields?)
396 
397  //checking if the data were changed
398  if( (data_.sources_density.changed() )
399  || (data_.sources_conc.changed() )
400  || (data_.sources_sigma.changed() )
402  || (data_.porosity.changed() ))
403  {
404  START_TIMER("sources_reinit");
405  for (loc_el = 0; loc_el < el_ds->lsize(); loc_el++)
406  {
407  ele_acc = mesh_->element_accessor(el_4_loc[loc_el]);
408  p = ele_acc.centre();
409 
410  por_m = data_.porosity.value(p, ele_acc);
411 
412  //if(data_.sources_density.changed_during_set_time)
413  sources_density[sbi][loc_el] = data_.sources_density.value(p, ele_acc)(sbi)/por_m;
414 
415  //if(data_.sources_conc.changed_during_set_time)
416  sources_conc[sbi][loc_el] = data_.sources_conc.value(p, ele_acc)(sbi);
417 
418  //if(data_.sources_sigma.changed_during_set_time)
419  sources_sigma[sbi][loc_el] = data_.sources_sigma.value(p, ele_acc)(sbi)/por_m;
420  }
421  END_TIMER("sources_reinit");
422 
423  Element *ele;
424  if (balance_ != nullptr)
425  {
426  START_TIMER("Balance source assembly");
427  balance_->start_source_assembly(sbi);
428 
429  //now computing source concentrations: density - sigma (source_conc - actual_conc)
430  for (loc_el = 0; loc_el < el_ds->lsize(); loc_el++)
431  {
432  ele = mesh_->element(el_4_loc[loc_el]);
433  p = ele->centre();
434 
435  csection = data_.cross_section.value(p, ele->element_accessor());
436  por_m = data_.porosity.value(p, ele->element_accessor());
437 
438  balance_->add_source_matrix_values(sbi, ele->region().bulk_idx(), {row_4_el[el_4_loc[loc_el]]}, {sources_sigma[sbi][loc_el]*ele->measure()*por_m*csection});
439  balance_->add_source_rhs_values(sbi, ele->region().bulk_idx(), {row_4_el[el_4_loc[loc_el]]}, {sources_density[sbi][loc_el]*ele->measure()*por_m*csection});
440  }
441 
442  balance_->finish_source_assembly(sbi);
443  END_TIMER("Balance source assembly");
444  }
445  }
446 
447 
448  //now computing source concentrations: density - sigma (source_conc - actual_conc)
449  START_TIMER("calculate sources_corr");
450  for (loc_el = 0; loc_el < el_ds->lsize(); loc_el++)
451  {
452  conc_diff = sources_conc[sbi][loc_el] - conc[sbi][loc_el];
453  if ( conc_diff > 0.0)
454  sources_corr[loc_el] = ( sources_density[sbi][loc_el]
455  + conc_diff * sources_sigma[sbi][loc_el] );
456  else
457  sources_corr[loc_el] = sources_density[sbi][loc_el];
458  }
459  END_TIMER("calculate sources_corr");
460 }
461 
462 
463 
465 {
466  ASSERT_EQUAL(time_->tlevel(), 0);
467 
469  data_.set_time(time_->step());
470 
472 
473  if (balance_ != nullptr)
474  {
475  START_TIMER("Convection balance zero time step");
476  balance_->units(
478  *data_.porosity.units()
479  *data_.conc_mobile.units());
480 
483  for (unsigned int sbi=0; sbi<n_subst_; ++sbi)
485 
487  }
488 
489  // write initial condition
490  output_data();
491 }
492 
493 
494 
496 
497  START_TIMER("convection-one step");
498 
499 
500  START_TIMER("data reinit");
501  data_.set_time(time_->step()); // set to the last computed time
502 
503  ASSERT(mh_dh, "Null MH object.\n" );
504  // update matrix and sources if neccessary
505 
506 
510 
511  // need new fixation of the time step
512 
515 
517  // scale boundary sources
518  for (unsigned int sbi=0; sbi<n_subst_; sbi++) VecScale(bcvcorr[sbi], time_->estimate_dt());
519 
520  need_time_rescaling = true;
521  } else {
522  // possibly read boundary conditions
523  if (data_.bc_conc.changed() ) {
525  // scale boundary sources
526  for (unsigned int sbi=0; sbi<n_subst_; sbi++) VecScale(bcvcorr[sbi], time_->dt());
527  }
528  }
529 
530  if (need_time_rescaling) {
532  // rescale matrix
533  MatShift(tm, -1.0);
534  MatScale(tm, time_->estimate_dt()/time_->dt() );
535  MatShift(tm, 1.0);
536 
537  for (unsigned int sbi=0; sbi<n_subst_; sbi++) VecScale(bcvcorr[sbi], time_->estimate_dt()/time_->dt());
538 
539  } else {
540  // scale fresh convection term matrix
541  MatScale(tm, time_->estimate_dt());
542  MatShift(tm, 1.0);
544 
545  }
546  need_time_rescaling = false;
547  }
548 
549  END_TIMER("data reinit");
550 
551 
552  // proceed to actually computed time
553  // explicit scheme use values from previous time and then set then new time
554  time_->next_time();
555 
556 
557  for (unsigned int sbi = 0; sbi < n_subst_; sbi++) {
558  // one step in MOBILE phase
559 
560  START_TIMER("compute_concentration_sources");
561  //sources update
563 
564  VecScale(v_sources_corr, time_->dt());
565  //vcumulative_corr[sbi] = 1.0 * bcvcorr[sbi] + v_sources_corr;
566  VecWAXPY(vcumulative_corr[sbi],1.0,bcvcorr[sbi],v_sources_corr);
567  END_TIMER("compute_concentration_sources");
568 
569  START_TIMER("mat mult");
570  VecCopy(vconc[sbi], vpconc[sbi]); // pconc = conc
571  MatMultAdd(tm, vpconc[sbi], vcumulative_corr[sbi], vconc[sbi]); // conc=tm*pconc + bc
572  END_TIMER("mat mult");
573  }
574 
575  END_TIMER("convection-one step");
576 }
577 
578 
579 void ConvectionTransport::set_target_time(double target_time)
580 {
581 
582  //sets target_mark_type (it is fixed) to be met in next_time()
583  time_->marks().add(TimeMark(target_time, target_mark_type));
584 
585  // make new time step fixation, invalidate scaling
586  // same is done when matrix has changed in compute_one_step
588 
589  // fixing convection time governor till next target_mark_type (got from TOS or other)
590  // may have marks for data changes
592  need_time_rescaling = true;
593 
594 }
595 
596 
597 //=============================================================================
598 // CREATE TRANSPORT MATRIX
599 //=============================================================================
601 
602  START_TIMER("convection_matrix_assembly");
603 
606  struct Edge *edg;
607  unsigned int n;
608  int s, j, np, rank, new_j, new_i;
609  double max_sum, aij, aii;
610 
611  MatZeroEntries(tm);
612 
613  MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
614  MPI_Comm_size(PETSC_COMM_WORLD, &np);
615 
616  double flux, flux2, edg_flux;
617 
618 
619  vector<double> edge_flow(mesh_->n_edges(),0.0);
620  for(unsigned int i=0; i < mesh_->n_edges() ; i++) { // calculate edge Qv
621  Edge &edg = mesh_->edges[i];
622  for( int s=0; s < edg.n_sides; s++) {
623  flux = mh_dh->side_flux( *(edg.side(s)) );
624  if ( flux > 0) edge_flow[i]+= flux;
625  }
626  }
627 
628  if (balance_ != nullptr)
629  balance_->start_mass_assembly(subst_idx);
630 
631  max_sum = 0.0;
632  aii = 0.0;
633 
634  for (unsigned int loc_el = 0; loc_el < el_ds->lsize(); loc_el++) {
635  elm = mesh_->element(el_4_loc[loc_el]);
636  new_i = row_4_el[elm.index()];
637 
638  double csection = data_.cross_section.value(elm->centre(), elm->element_accessor());
639  double por_m = data_.porosity.value(elm->centre(), elm->element_accessor());
640 
641  if (balance_ != nullptr)
642  {
643  for (unsigned int sbi=0; sbi<n_subst_; ++sbi)
644  balance_->add_mass_matrix_values(subst_idx[sbi], elm->region().bulk_idx(), {row_4_el[el_4_loc[loc_el]]}, {csection*por_m*elm->measure()} );
645  }
646 
647  FOR_ELEMENT_SIDES(elm,si) {
648  // same dim
649  flux = mh_dh->side_flux( *(elm->side(si)) );
650  if (elm->side(si)->cond() == NULL) {
651  edg = elm->side(si)->edge();
652  edg_flux = edge_flow[ elm->side(si)->edge_idx() ];
653  FOR_EDGE_SIDES(edg,s)
654  // this test should also eliminate sides facing to lower dim. elements in comp. neighboring
655  // These edges on these sides should have just one side
656  if (edg->side(s) != elm->side(si)) {
657  j = ELEMENT_FULL_ITER(mesh_, edg->side(s)->element()).index();
658  new_j = row_4_el[j];
659 
660  flux2 = mh_dh->side_flux( *(edg->side(s)));
661  if ( flux2 > 0.0 && flux <0.0)
662  aij = -(flux * flux2 / ( edg_flux * elm->measure() * csection * por_m) );
663  else aij =0;
664  MatSetValue(tm, new_i, new_j, aij, INSERT_VALUES);
665  }
666  if (flux > 0.0)
667  aii -= (flux / (elm->measure() * csection * por_m) );
668  } else {
669  if (flux > 0.0)
670  aii -= (flux / (elm->measure() * csection * por_m) );
671  }
672  } // end same dim //ELEMENT_SIDES
673 
674  FOR_ELM_NEIGHS_VB(elm,n) // comp model
675  {
676  el2 = ELEMENT_FULL_ITER(mesh_, elm->neigh_vb[n]->side()->element() ); // higher dim. el.
677  ASSERT( el2 != elm, "Elm. same\n");
678  new_j = row_4_el[el2.index()];
679  flux = mh_dh->side_flux( *(elm->neigh_vb[n]->side()) );
680 
681  // volume source - out-flow from higher dimension
682  if (flux > 0.0) aij = flux / (elm->measure() * csection * por_m);
683  else aij=0;
684  MatSetValue(tm, new_i, new_j, aij, INSERT_VALUES);
685  // out flow from higher dim. already accounted
686 
687  // volume drain - in-flow to higher dimension
688  if (flux < 0.0) {
689  aii -= (-flux) / (elm->measure() * csection * por_m); // diagonal drain
690  aij = (-flux) / (el2->measure() *
691  data_.cross_section.value(el2->centre(), el2->element_accessor()) *
692  data_.porosity.value(el2->centre(), el2->element_accessor()));
693  } else aij=0;
694  MatSetValue(tm, new_j, new_i, aij, INSERT_VALUES);
695  }
696 
697  MatSetValue(tm, new_i, new_i, aii, INSERT_VALUES);
698 
699  if (fabs(aii) > max_sum)
700  max_sum = fabs(aii);
701  aii = 0.0;
702  } // END ELEMENTS
703 
704  if (balance_ != nullptr)
705  balance_->finish_mass_assembly(subst_idx);
706 
707  double glob_max_sum;
708 
709  MPI_Allreduce(&max_sum,&glob_max_sum,1,MPI_DOUBLE,MPI_MAX,PETSC_COMM_WORLD);
710  cfl_max_step = 1 / glob_max_sum;
711 
712  MatAssemblyBegin(tm, MAT_FINAL_ASSEMBLY);
713  MatAssemblyEnd(tm, MAT_FINAL_ASSEMBLY);
714 
716  END_TIMER("convection_matrix_assembly");
717 
719 }
720 
721 
722 
723 
724 
725 //=============================================================================
726 // OUTPUT VECTOR GATHER
727 //=============================================================================
729 
730  unsigned int sbi;
731  IS is;
732 
733  ISCreateGeneral(PETSC_COMM_SELF, mesh_->n_elements(), row_4_el, PETSC_COPY_VALUES, &is); //WithArray
734  VecScatterCreate(vconc[0], is, out_conc[0].get_data_petsc(), PETSC_NULL, &vconc_out_scatter);
735  for (sbi = 0; sbi < n_subst_; sbi++) {
736  VecScatterBegin(vconc_out_scatter, vconc[sbi], out_conc[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
737  VecScatterEnd(vconc_out_scatter, vconc[sbi], out_conc[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
738  }
739  VecScatterDestroy(&(vconc_out_scatter));
740  ISDestroy(&(is));
741 }
742 
743 
745  return conc;
746 }
747 
748 void ConvectionTransport::get_par_info(int * &el_4_loc_out, Distribution * &el_distribution_out){
749  el_4_loc_out = this->el_4_loc;
750  el_distribution_out = this->el_ds;
751  return;
752 }
753 
755  return el_4_loc;
756 }
757 
759  return row_4_el;
760 }
761 
762 
763 
765 {
766  Vec vpconc_diff;
767  const double *pconc;
768  double *pconc_diff;
769 
770  for (unsigned int sbi=0; sbi<n_subst_; ++sbi)
771  {
772  VecDuplicate(vpconc[sbi], &vpconc_diff);
773  VecGetArrayRead(vpconc[sbi], &pconc);
774  VecGetArray(vpconc_diff, &pconc_diff);
775  for (unsigned int loc_el=0; loc_el<el_ds->lsize(); ++loc_el)
776  {
777  if (pconc[loc_el] < sources_conc[sbi][loc_el])
778  pconc_diff[loc_el] = sources_conc[sbi][loc_el] - pconc[loc_el];
779  else
780  pconc_diff[loc_el] = 0;
781  }
782  balance_->calculate_cumulative_sources(sbi, vpconc_diff, time_->dt());
783  balance_->calculate_cumulative_fluxes(sbi, vpconc[sbi], time_->dt());
784 
785  VecRestoreArray(vpconc_diff, &pconc_diff);
786  VecRestoreArrayRead(vpconc[sbi], &pconc);
787  VecDestroy(&vpconc_diff);
788  }
789 }
790 
791 
793 {
794  Vec vconc_diff;
795  const double *conc;
796  double *conc_diff;
797 
798  for (unsigned int sbi=0; sbi<n_subst_; ++sbi)
799  {
800  VecDuplicate(vconc[sbi], &vconc_diff);
801  VecGetArrayRead(vconc[sbi], &conc);
802  VecGetArray(vconc_diff, &conc_diff);
803  for (unsigned int loc_el=0; loc_el<el_ds->lsize(); ++loc_el)
804  {
805  if (conc[loc_el] < sources_conc[sbi][loc_el])
806  conc_diff[loc_el] = sources_conc[sbi][loc_el] - conc[loc_el];
807  else
808  conc_diff[loc_el] = 0;
809  }
810 
811  balance_->calculate_mass(sbi, vconc[sbi]);
812  balance_->calculate_source(sbi, vconc_diff);
813  balance_->calculate_flux(sbi, vconc[sbi]);
814 
815  VecRestoreArray(vconc_diff, &conc_diff);
816  VecRestoreArrayRead(vconc[sbi], &conc);
817  VecDestroy(&vconc_diff);
818  }
819 }
820 
821 
823 
824  if (time_->is_current( time_->marks().type_output() )) {
826 
829 
830  }
831 }
void output_type(OutputTime::DiscreteSpace rt)
Definition: field_set.hh:194
unsigned int size() const
get global size
void set_input_list(Input::Array input_list)
Definition: field_set.hh:164
void compute_concentration_sources(unsigned int sbi)
Definition: transport.cc:387
FieldSet * eq_data_
Definition: equation.hh:227
void set_limit_side(LimitSide side)
Definition: field_set.hh:171
std::vector< VectorSeqDouble > out_conc
Definition: transport.h:271
double measure() const
Definition: elements.cc:101
double time_changed() const
double * sources_corr
Definition: transport.h:237
void update_solution() override
Definition: transport.cc:495
Accessor to input data conforming to declared Array.
Definition: accessors.hh:558
double end_time() const
End time.
double transport_matrix_time
Definition: transport.h:258
int tlevel() const
Field< 3, FieldValue< 3 >::Scalar > cross_section
Pointer to DarcyFlow field cross_section.
void id_maps(int n_ids, int *id_4_old, Distribution *&new_ds, int *&id_4_loc, int *&new_4_id)
const std::vector< std::string > & names()
Definition: substance.hh:97
void add_admissible_field_names(const Input::Array &in_array)
Registers names of output fields that can be written using this stream.
Definition: output_time.cc:165
#define FOR_EDGE_SIDES(i, j)
Definition: edges.h:53
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:364
void alloc_transport_vectors()
Definition: transport.cc:241
double ** sources_sigma
Definition: transport.h:242
BCField< 3, FieldValue< 3 >::Vector > bc_conc
Definition: transport.h:97
double fix_dt_until_mark()
Fixing time step until fixed time mark.
MultiField< 3, FieldValue< 3 >::Scalar > conc_mobile
Calculated concentrations in the mobile zone.
Definition: transport.h:103
void next_time()
Proceed to the next time according to current estimated time step.
TimeMark::Type target_mark_type
TimeMark type for time marks denoting end of every time interval where transport matrix remains const...
Definition: transport.h:246
TimeMark::Type type_output()
Definition: time_marks.hh:203
void set_initial_condition()
Definition: transport.cc:222
???
void initialize(const Input::Array &in_array)
Read from input array.
Definition: substance.cc:68
void set_boundary_conditions()
Definition: transport.cc:319
void set_time(const TimeStep &time)
Definition: field_set.hh:186
RegionSet get_region_set(const string &set_name) const
Definition: region.cc:361
const MH_DofHandler * mh_dh
#define ELEMENT_FULL_ITER(_mesh_, i)
Definition: mesh.h:372
Definition: mesh.h:109
Fields computed from the mesh data.
Field< 3, FieldValue< 3 >::Vector > sources_conc
Iterator< Ret > find(const string &key) const
#define FOR_ELEMENT_SIDES(i, j)
Definition: elements.h:151
int index() const
Definition: sys_vector.hh:88
bool is_current(const TimeMark::Type &mask) const
int n_sides
Definition: edges.h:48
Field< 3, FieldValue< 3 >::Scalar > porosity
Mobile porosity.
Definition: edges.h:38
const RegionDB & region_db() const
Definition: mesh.h:155
ElementAccessor< 3 > element_accessor(unsigned int idx, bool boundary=false)
Definition: mesh.cc:670
double ** conc
Concentrations for phase, substance, element.
Definition: transport.h:263
void calculate_instant_balance()
Definition: transport.cc:792
const TimeStep & step(int index=-1) const
virtual ~ConvectionTransport()
Definition: transport.cc:185
double t() const
void get_par_info(int *&el_4_loc, Distribution *&el_ds)
Definition: transport.cc:748
#define ADD_FIELD(name,...)
Definition: field_set.hh:260
Basic time management functionality for unsteady (and steady) solvers (class Equation).
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Partitioning * get_part()
Definition: mesh.cc:191
void zero_time_step() override
Definition: transport.cc:464
unsigned int size() const
Definition: substance.hh:99
static TimeMarks & marks()
void output_vector_gather()
Definition: transport.cc:728
Basic time management class.
Specification of transport model interface.
double estimate_dt() const
Estimate choice of next time step according to actual setting of constraints.
OutputTime * output_stream_
Definition: transport.h:276
ConvectionTransport(Mesh &init_mesh, const Input::Record &in_rec)
Definition: transport.cc:97
void add(const TimeMark &mark)
Definition: time_marks.cc:88
unsigned int n_elements() const
Definition: mesh.h:141
#define ASSERT(...)
Definition: global_defs.h:121
bool is_local(unsigned int idx) const
identify local index
static OutputTime * create_output_stream(const Input::Record &in_rec)
This method delete all object instances of class OutputTime stored in output_streams vector...
Definition: output_time.cc:141
static Input::Type::Selection sorption_type_selection
Definition: transport.h:83
#define ASSERT_EQUAL(a, b)
Definition: global_defs.h:136
Input::Record output_rec
Record with output specification.
Definition: transport.h:274
TimeMark::Type equation_fixed_mark_type() const
Region region() const
Definition: elements.cc:167
static constexpr Mask equation_external_output
Match an output field, that can be also copy of other field.
Definition: field_flag.hh:42
unsigned int begin(int proc) const
get starting local index
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
const Ret val(const string &key) const
static auto region_id(Mesh &mesh) -> IndexField
#define START_TIMER(tag)
Starts a timer with specified tag.
Mesh * mesh_
Definition: equation.hh:218
Element * element()
Definition: boundaries.cc:47
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:312
boost::shared_ptr< Balance > balance_
(new) object for calculation and writing the mass balance to file.
void set_up_components()
void mark_input_times(TimeMark::Type mark_type)
Definition: field_set.hh:201
unsigned int n_subst_
Number of transported substances.
vector< unsigned int > subst_idx
List of indices used to call balance methods for a set of quantities.
Definition: transport.h:284
void mark_output_times(const TimeGovernor &tg)
Definition: output_time.cc:182
#define MPI_Comm_size
Definition: mpi.h:235
#define MPI_DOUBLE
Definition: mpi.h:156
Vec * vconc
Concentration vectors for mobile phase.
Definition: transport.h:261
void * xmalloc(size_t size)
Memory allocation with checking.
Definition: system.cc:209
#define INPUT_CHECK(i,...)
Debugging macros.
Definition: global_defs.h:61
#define MPI_Comm_rank
Definition: mpi.h:236
FieldSet output_fields
Fields indended for output, i.e. all input fields plus those representing solution.
Definition: transport.h:107
Field< 3, FieldValue< 3 >::Integer > region_id
Definition: transport.h:102
void create_transport_matrix_mpi()
Definition: transport.cc:600
Support classes for parallel programing.
#define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm)
Definition: mpi.h:612
Field< 3, FieldValue< 3 >::Vector > sources_sigma
Concentration sources - Robin type, in_flux = sources_sigma * (sources_conc - mobile_conc) ...
void alloc_transport_structs_mpi()
Definition: transport.cc:276
double side_flux(const Side &side) const
temporary replacement for DofHandler accessor, flux through given side
static OldBcdInput * instance()
Definition: old_bcd.cc:30
bool is_convection_matrix_scaled
Definition: transport.h:235
#define ELEMENT_FULL_ITER_NULL(_mesh_)
Definition: mesh.h:378
static Input::Type::Selection output_selection
Definition: transport.h:85
void output(OutputTime *stream)
Definition: field_set.cc:143
const Selection & close() const
SubstanceList substances_
Transported substances.
void set_components(const std::vector< string > &names)
Definition: field_set.hh:151
ElementFullIter element() const
Definition: side_impl.hh:41
int set_upper_constraint(double upper)
Sets upper constraint for the next time step estimating.
Field< 3, FieldValue< 3 >::Vector > sources_density
Concentration sources - density of substance source, only positive part is used.
VecScatter vconc_out_scatter
Definition: transport.h:252
double ** sources_density
temporary arrays to store constant values of fields over time interval
Definition: transport.h:242
double dt() const
arma::vec3 centre() const
Definition: elements.cc:132
void add_factory(std::shared_ptr< FactoryBase > factory)
Definition: field.impl.hh:469
virtual void output_data() override
Write computed fields.
Definition: transport.cc:822
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:216
Distributed sparse graphs, partitioning.
void set_target_time(double target_time)
Definition: transport.cc:579
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:80
void calculate_cumulative_balance()
Definition: transport.cc:764
FieldCommon & name(const string &name)
Definition: field_common.hh:73
#define END_TIMER(tag)
Ends a timer with specified tag.
arma::vec::fixed< spacedim > centre() const
Definition: accessors.hh:81
#define FOR_ELM_NEIGHS_VB(i, j)
Definition: elements.h:152
ElementAccessor< 3 > element_accessor() const
Gets ElementAccessor of this element.
Definition: elements.cc:160
#define MPI_MAX
Definition: mpi.h:197
double ** cumulative_corr
Definition: transport.h:269
bool changed() const
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:157
Class used for marking specified times at which some events occur.
Definition: time_marks.hh:49
unsigned int n_substances() override
Returns number of trnasported substances.
FieldCommon & flags(FieldFlag::Flags::Mask mask)
unsigned int n_edges() const
Definition: mesh.h:149
double ** get_concentration_matrix()
Definition: transport.cc:744
#define xfree(p)
Definition: system.hh:108
Class for representation SI units of Fields.
Definition: unit_si.hh:31
#define MPI_Barrier(comm)
Definition: mpi.h:531
UnitSI & md(int exp=-1)
Method sets value of exponent for m^{-d}, where d is dimension of region.
Definition: unit_si.cc:91
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:44
Distribution * el_ds
Definition: transport.h:281
SideIter side(const unsigned int i) const
Definition: edges.h:43
Template for classes storing finite set of named values.
Field< 3, FieldValue< 3 >::Vector > init_conc
Initial concentrations.
Definition: transport.h:100
ElementAccessor< 3 > element_accessor()
Definition: boundaries.cc:55
void make_transport_partitioning()
Definition: transport.cc:161
TimeGovernor * time_
Definition: equation.hh:219
double ** sources_conc
Definition: transport.h:242
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:205
unsigned int lsize(int proc) const
get local size