Flow123d  jenkins-Flow123d-windows32-release-multijob-51
darcy_flow_mh_output.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: darcy_flow_mh.hh 877 2011-02-04 13:13:25Z jakub.sistek $
21  * $Revision: 877 $
22  * $LastChangedBy: jakub.sistek $
23  * $LastChangedDate: 2011-02-04 14:13:25 +0100 (Fri, 04 Feb 2011) $
24  *
25  * @file
26  * @brief Output class for darcy_flow_mh model.
27  * @ingroup flow
28  *
29  * @author Jan Brezina
30  *
31  */
32 
33 
34 #include <vector>
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 
39 #include <system/global_defs.h>
40 
41 #include "flow/mh_fe_values.hh"
42 #include "flow/darcy_flow_mh.hh"
44 #include "system/system.hh"
45 #include "system/sys_profiler.hh"
46 #include "system/xio.h"
47 
48 #include "fem/dofhandler.hh"
49 #include "fields/field_fe.hh"
50 
51 #include "io/output.h"
52 #include "mesh/partitioning.hh"
53 
54 
55 
56 namespace it = Input::Type;
57 
59  = DarcyFlowMH::EqData().make_output_field_selection("DarcyMHOutput_Selection", "Selection of fields available for output.")
60  .copy_values(OutputFields().make_output_field_selection("").close())
61  .close();
62 
64  = it::Record("DarcyMHOutput", "Parameters of MH output.")
66  "Parameters of output stream.")
67  .declare_key("output_fields", it::Array(OutputFields::output_selection),
68  it::Default::obligatory(), "List of fields to write to output file.")
69  .declare_key("balance_output", it::FileName::output(), it::Default("water_balance.txt"),
70  "Output file for water balance table.")
71  .declare_key("compute_errors", it::Bool(), it::Default("false"),
72  "SPECIAL PURPOSE. Computing errors pro non-compatible coupling.")
74  "Output file with raw data form MH module.");
75 
76 
78 {
79  *this += field_ele_pressure.name("pressure_p0").units(UnitSI().m());
80  *this += field_node_pressure.name("pressure_p1").units(UnitSI().m());
81  *this += field_ele_piezo_head.name("piezo_head_p0").units(UnitSI().m());
82  *this += field_ele_flux.name("velocity_p0").units(UnitSI().m().s(-1));
83  *this += subdomain.name("subdomain").units( UnitSI::dimensionless() );
84 
85  fields_for_output += *this;
86 
87  *this += pressure_diff.name("pressure_diff").units(UnitSI().m());
88  *this += velocity_diff.name("velocity_diff").units(UnitSI().m().s(-1));
89  *this += div_diff.name("div_diff").units(UnitSI().s(-1));
90 
91 }
92 
93 
95 : darcy_flow(flow),
96  mesh_(&darcy_flow->mesh()),
97  in_rec_(in_rec),
98  balance_output_file(NULL),
99  raw_output_file(NULL)
100 {
101 
102 
103 
104  // we need to add data from the flow equation at this point, not in constructor of OutputFields
107 
108  // create shared pointer to a FieldElementwise and push this Field to output_field on all regions
109  ele_pressure.resize(mesh_->n_elements());
110  auto ele_pressure_ptr=make_shared< FieldElementwise<3, FieldValue<3>::Scalar> >(ele_pressure, 1);
112 
113  dh = new DOFHandlerMultiDim(*mesh_);
115  corner_pressure.resize(dh->n_global_dofs());
116  VecCreateSeqWithArray(PETSC_COMM_SELF, 1, dh->n_global_dofs(), &(corner_pressure[0]), &vec_corner_pressure);
117 
118  auto corner_ptr = make_shared< FieldFE<3, FieldValue<3>::Scalar> >();
119  corner_ptr->set_fe_data(dh, &map1, &map2, &map3, &vec_corner_pressure);
120 
123 
124  ele_piezo_head.resize(mesh_->n_elements());
126  make_shared< FieldElementwise<3, FieldValue<3>::Scalar> >(ele_piezo_head, 1));
127 
128  ele_flux.resize(3*mesh_->n_elements());
130  make_shared< FieldElementwise<3, FieldValue<3>::VectorFixed> >(ele_flux, 3));
131 
132  auto &vec_int_sub = mesh_->get_part()->seq_output_partition();
133  subdomains.resize(vec_int_sub.size());
134  for(unsigned int i=0; i<subdomains.size();i++)
135  subdomains[i]=vec_int_sub[i];
137  make_shared< FieldElementwise<3, FieldValue<3>::Integer> >(subdomains, 1));
138 
140 
141 
145 
146  int rank;
148 
149  if (rank == 0) {
150  // temporary solution for balance output
151  balance_output_file = xfopen( in_rec.val<FilePath>("balance_output"), "wt");
152 
153  // optionally open raw output file
154  FilePath raw_output_file_path;
155  if (in_rec.opt_val("raw_flow_output", raw_output_file_path)) {
156  xprintf(Msg, "Opening raw output: %s\n", string(raw_output_file_path).c_str() );
157  raw_output_file = xfopen(raw_output_file_path, "wt");
158  }
159 
160  }
161 }
162 
163 
164 
166 
169  VecDestroy(&vec_corner_pressure);
170  delete output_stream;
171 
172  delete dh;
173 };
174 
175 
176 
177 
178 
179 //=============================================================================
180 // CONVERT SOLUTION, CALCULATE BALANCES, ETC...
181 //=============================================================================
182 
183 
185 {
186  START_TIMER("Darcy output");
187 
188  if (darcy_flow->time().is_current( TimeGovernor::marks().type_output() )) {
189 
192 
194 
195  water_balance();
196 
197  if (in_rec_.val<bool>("compute_errors")) compute_l2_difference();
198 
202 
204 
205  }
206 
207 }
208 
209 
210 //=============================================================================
211 // FILL TH "SCALAR" FIELD FOR ALL ELEMENTS IN THE MESH
212 //=============================================================================
213 
215  unsigned int sol_size;
216  double *sol;
217 
218  darcy_flow->get_solution_vector(sol, sol_size);
219  unsigned int soi = mesh_->n_sides();
220  unsigned int i = 0;
221  FOR_ELEMENTS(mesh_,ele) {
222  ele_pressure[i] = sol[ soi];
223  ele_piezo_head[i] = sol[soi ] + ele->centre()[Mesh::z_coord];
224  i++; soi++;
225  }
226 }
227 
228 
229 
230 /****
231  * compute Darcian velocity in centre of elements
232  *
233  */
236  MHFEValues fe_values;
237 
238  int i_side=0;
239  FOR_ELEMENTS(mesh_, ele) {
240  arma::vec3 flux_in_centre;
241  flux_in_centre.zeros();
242 
243  fe_values.update(ele,
247 
248  for (unsigned int li = 0; li < ele->n_sides(); li++) {
249  flux_in_centre += dh.side_flux( *(ele->side( li ) ) )
250  * fe_values.RT0_value( ele, ele->centre(), li )
251  / darcy_flow->data_.cross_section.value(ele->centre(), ele->element_accessor() );
252  }
253 
254  for(unsigned int j=0; j<3; j++)
255  ele_flux[3*i_side+j]=flux_in_centre[j];
256 
257  i_side++;
258  }
259 
260 }
261 
262 
264 {
265  unsigned int ndofs = max(dh->fe<1>()->n_dofs(), max(dh->fe<2>()->n_dofs(), dh->fe<3>()->n_dofs()));
266  unsigned int indices[ndofs];
267  unsigned int i_node;
268  FOR_ELEMENTS(mesh_, ele)
269  {
270  dh->get_dof_indices(ele, indices);
271  FOR_ELEMENT_NODES(ele, i_node)
272  {
273  corner_pressure[indices[i_node]] = node_scalar[mesh_->node_vector.index(ele->node[i_node])];
274  }
275  }
276 }
277 
278 
279 //=============================================================================
280 // pressure interpolation
281 //
282 // some sort of weighted average over elements and sides/edges of an node
283 //
284 // TODO:
285 // questions:
286 // - explain details of averaging and motivation for this type
287 // - edge scalars are stronger since thay are computed twice by each side
288 // - why division by (nod.aux-1)
289 // - ?implement without TED, TSD global arrays with single loop over elements, sides and one loop over nodes for normalization
290 //
291 //=============================================================================
292 
294 
295  vector<double> scalars(mesh_->n_nodes());
296 
297  double dist; //!< tmp variable for storing particular distance node --> element, node --> side*/
298 
299  /** Iterators */
300  const Node * node;
301 
302  int n_nodes = mesh_->node_vector.size(); //!< number of nodes in the mesh */
303  int node_index = 0; //!< index of each node */
304 
305  int* sum_elements = new int [n_nodes]; //!< sum elements joined to node */
306  int* sum_sides = new int [n_nodes]; //!< sum sides joined to node */
307  double* sum_ele_dist = new double [n_nodes]; //!< sum distances to all joined elements */
308  double* sum_side_dist = new double [n_nodes]; //!< Sum distances to all joined sides */
309 
310  /** tmp variables, will be replaced by ini keys
311  * TODO include them into ini file*/
312  bool count_elements = true; //!< scalar is counted via elements*/
313  bool count_sides = true; //!< scalar is counted via sides */
314 
315 
317 
318  /** init arrays */
319  for (int i = 0; i < n_nodes; i++){
320  sum_elements[i] = 0;
321  sum_sides[i] = 0;
322  sum_ele_dist[i] = 0.0;
323  sum_side_dist[i] = 0.0;
324  scalars[i] = 0.0;
325  };
326 
327  /**first pass - calculate sums (weights)*/
328  if (count_elements){
329  FOR_ELEMENTS(mesh_, ele)
330  for (unsigned int li = 0; li < ele->n_nodes(); li++) {
331  node = ele->node[li]; //!< get Node pointer from element */
332  node_index = mesh_->node_vector.index(node); //!< get nod index from mesh */
333 
334  dist = sqrt(
335  ((node->getX() - ele->centre()[ 0 ])*(node->getX() - ele->centre()[ 0 ])) +
336  ((node->getY() - ele->centre()[ 1 ])*(node->getY() - ele->centre()[ 1 ])) +
337  ((node->getZ() - ele->centre()[ 2 ])*(node->getZ() - ele->centre()[ 2 ]))
338  );
339  sum_ele_dist[node_index] += dist;
340  sum_elements[node_index]++;
341  }
342  }
343  if (count_sides){
344  FOR_SIDES(mesh_, side) {
345  for (unsigned int li = 0; li < side->n_nodes(); li++) {
346  node = side->node(li);//!< get Node pointer from element */
347  node_index = mesh_->node_vector.index(node); //!< get nod index from mesh */
348  dist = sqrt(
349  ((node->getX() - side->centre()[ 0 ])*(node->getX() - side->centre()[ 0 ])) +
350  ((node->getY() - side->centre()[ 1 ])*(node->getY() - side->centre()[ 1 ])) +
351  ((node->getZ() - side->centre()[ 2 ])*(node->getZ() - side->centre()[ 2 ]))
352  );
353 
354  sum_side_dist[node_index] += dist;
355  sum_sides[node_index]++;
356  }
357  }
358  }
359 
360  /**second pass - calculate scalar */
361  if (count_elements){
362  FOR_ELEMENTS(mesh_, ele)
363  for (unsigned int li = 0; li < ele->n_nodes(); li++) {
364  node = ele->node[li];//!< get Node pointer from element */
365  node_index = mesh_->node_vector.index(node); //!< get nod index from mesh */
366 
367  /**TODO - calculate it again or store it in prior pass*/
368  dist = sqrt(
369  ((node->getX() - ele->centre()[ 0 ])*(node->getX() - ele->centre()[ 0 ])) +
370  ((node->getY() - ele->centre()[ 1 ])*(node->getY() - ele->centre()[ 1 ])) +
371  ((node->getZ() - ele->centre()[ 2 ])*(node->getZ() - ele->centre()[ 2 ]))
372  );
373  scalars[node_index] += ele_pressure[ele.index()] *
374  (1 - dist / (sum_ele_dist[node_index] + sum_side_dist[node_index])) /
375  (sum_elements[node_index] + sum_sides[node_index] - 1);
376  }
377  }
378  if (count_sides) {
379  FOR_SIDES(mesh_, side) {
380  for (unsigned int li = 0; li < side->n_nodes(); li++) {
381  node = side->node(li);//!< get Node pointer from element */
382  node_index = mesh_->node_vector.index(node); //!< get nod index from mesh */
383 
384  /**TODO - calculate it again or store it in prior pass*/
385  dist = sqrt(
386  ((node->getX() - side->centre()[ 0 ])*(node->getX() - side->centre()[ 0 ])) +
387  ((node->getY() - side->centre()[ 1 ])*(node->getY() - side->centre()[ 1 ])) +
388  ((node->getZ() - side->centre()[ 2 ])*(node->getZ() - side->centre()[ 2 ]))
389  );
390 
391 
392  scalars[node_index] += dh.side_scalar( *side ) *
393  (1 - dist / (sum_ele_dist[node_index] + sum_side_dist[node_index])) /
394  (sum_sides[node_index] + sum_elements[node_index] - 1);
395  }
396  }
397  }
398 
399  /** free memory */
400  delete [] sum_elements;
401  delete [] sum_sides;
402  delete [] sum_ele_dist;
403  delete [] sum_side_dist;
404 
405  make_corner_scalar(scalars);
406 }
407 
408 
409 //=============================================================================
410 //
411 //=============================================================================
412 
415  if (balance_output_file == NULL) return;
416 
417  //BOUNDARY
418  //struct Boundary *bcd;
419  std::vector<double> bcd_balance( mesh_->region_db().boundary_size(), 0.0 );
420  std::vector<double> bcd_plus_balance( mesh_->region_db().boundary_size(), 0.0 );
421  std::vector<double> bcd_minus_balance( mesh_->region_db().boundary_size(), 0.0 );
422 
423  using namespace std;
424  //printing the head of water balance file
425  unsigned int c = 5; //column number without label
426  unsigned int w = 14; //column width
427  unsigned int wl = 2*(w-5)+7; //label column width
428  stringstream s; //helpful stringstream
429  string bc_head_format = "# %-*s%-*s%-*s%-*s%-*s%-*s\n",
430  bc_format = "%*s%-*d%-*s %-*g%-*g%-*g%-*g\n",
431  bc_total_format = "# %-*s%-*g%-*g%-*g\n\n\n";
432  s << setw((w*c+wl-15)/2) << setfill('-') << "-"; //drawing half line
433  fprintf(balance_output_file,"# %s WATER BALANCE %s\n",s.str().c_str(), s.str().c_str());
434  fprintf(balance_output_file,"# Time of computed water balance: %f\n\n\n",darcy_flow->time().t());
435 
436  fprintf(balance_output_file,"# Boundary water balance:\n");
437  fprintf(balance_output_file,bc_head_format.c_str(),w,"[boundary_id]",wl,"[label]",
438  w,"[total_balance]",w,"[total_outflow]",w,"[total_inflow]",w,"[time]");
439  s.clear();
440  s.str(std::string());
441  s << setw(w*c+wl) << setfill('-') << "-";
442  fprintf(balance_output_file,"# %s\n",s.str().c_str()); //drawing long line
443 
444  //computing water balance over boundaries
445  FOR_BOUNDARIES(mesh_, bcd) {
446  // !! there can be more sides per one boundary
447  double flux = dh.side_flux( *(bcd->side()) );
448 
449  Region r = bcd->region();
450  if (! r.is_valid()) xprintf(Msg, "Invalid region, ele % d, edg: % d\n", bcd->bc_ele_idx_, bcd->edge_idx_);
451  unsigned int bc_region_idx = r.boundary_idx();
452  bcd_balance[bc_region_idx] += flux;
453 
454  if (flux > 0) bcd_plus_balance[bc_region_idx] += flux;
455  else bcd_minus_balance[bc_region_idx] += flux;
456  }
457  //printing water balance over boundaries
458  const RegionSet & b_set = mesh_->region_db().get_region_set("BOUNDARY");
459  double total_balance = 0, // for computing total balance on boundary
460  total_inflow = 0,
461  total_outflow = 0;
462  for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
463  total_balance += bcd_balance[reg->boundary_idx()];
464  total_outflow += bcd_plus_balance[reg->boundary_idx()];
465  total_inflow += bcd_minus_balance[reg->boundary_idx()];
466  fprintf(balance_output_file, bc_format.c_str(),2,"",w,reg->id(),wl,reg->label().c_str(),
467  w, bcd_balance[reg->boundary_idx()], w, bcd_plus_balance[reg->boundary_idx()],
468  w, bcd_minus_balance[reg->boundary_idx()], w, darcy_flow->time().t());
469  }
470  //total boundary balance
471  fprintf(balance_output_file,"# %s\n",s.str().c_str()); // drawing long line
472  fprintf(balance_output_file, bc_total_format.c_str(),w+wl+2,"total boundary balance",
473  w,total_balance, w, total_outflow, w, total_inflow);
474 
475  //SOURCES
476  string src_head_format = "# %-*s%-*s%-*s%-*s%-*s\n",
477  src_format = "%*s%-*d%-*s %-*g%-*s%-*g\n",
478  src_total_format = "# %-*s%-*g\n\n\n";
479  //computing water balance of sources
480  fprintf(balance_output_file,"# Source fluxes over material subdomains:\n"); //head
481  fprintf(balance_output_file,src_head_format.c_str(),w,"[region_id]",wl,"[label]",
482  w,"[total_balance]",2*w,"",w,"[time]");
483  fprintf(balance_output_file,"# %s\n",s.str().c_str()); //long line
484  std::vector<double> src_balance( mesh_->region_db().bulk_size(), 0.0 ); // initialize by zero
485  FOR_ELEMENTS(mesh_, elm) {
486  src_balance[elm->element_accessor().region().bulk_idx()] += elm->measure() *
487  darcy_flow->data_.cross_section.value(elm->centre(), elm->element_accessor()) *
488  darcy_flow->data_.water_source_density.value(elm->centre(), elm->element_accessor());
489  }
490 
491  total_balance = 0;
492  //printing water balance of sources
493  const RegionSet & bulk_set = mesh_->region_db().get_region_set("BULK");
494  for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
495  {
496  total_balance += src_balance[reg->bulk_idx()];
497  //"%*s%-*d%-*s %-*g%-*s%-*g\n";
498  fprintf(balance_output_file, src_format.c_str(), 2,"", w, reg->id(), wl,
499  reg->label().c_str(), w, src_balance[reg->bulk_idx()],2*w,"", w,darcy_flow->time().t());
500  }
501  //total sources balance
502  fprintf(balance_output_file,"# %s\n",s.str().c_str()); //drawing long line
503  fprintf(balance_output_file, src_total_format.c_str(),w+wl+2,"total sources balance",
504  w,total_balance);
505 }
506 
507 
508 /*
509  * Output of internal flow data.
510  */
512 {
514 
515  if (raw_output_file == NULL) return;
516 
517  char dbl_fmt[ 16 ]= "%.8g ";
518  // header
519  xfprintf( raw_output_file, "// fields:\n//ele_id ele_presure flux_in_barycenter[3] n_sides side_pressures[n] side_fluxes[n]\n");
520  xfprintf( raw_output_file, "$FlowField\nT=");
521  xfprintf( raw_output_file, dbl_fmt, darcy_flow->time().t());
522  xfprintf( raw_output_file, "\n%d\n", mesh_->n_elements() );
523 
524  unsigned int i;
525  int cit = 0;
526  FOR_ELEMENTS( mesh_, ele ) {
527  xfprintf( raw_output_file, "%d ", ele.id());
528  xfprintf( raw_output_file, dbl_fmt, ele_pressure[cit]);
529  for (i = 0; i < 3; i++)
530  xfprintf( raw_output_file, dbl_fmt, ele_flux[3*cit+i]);
531 
532  xfprintf( raw_output_file, " %d ", ele->n_sides());
533  for (i = 0; i < ele->n_sides(); i++)
534  xfprintf( raw_output_file, dbl_fmt, dh.side_scalar( *(ele->side(i) ) ) );
535  for (i = 0; i < ele->n_sides(); i++)
536  xfprintf( raw_output_file, dbl_fmt, dh.side_flux( *(ele->side(i) ) ) );
537 
538  xfprintf( raw_output_file, "\n" );
539  cit ++;
540  }
541  xfprintf( raw_output_file, "$EndFlowField\n\n" );
542 }
543 
544 
546 #include "fem/fe_p.hh"
547 #include "fem/fe_values.hh"
548 #include "fem/mapping_p1.hh"
549 #include "fields/field_python.hh"
550 #include "fields/field_values.hh"
551 
553 
554 /*
555 * Calculate approximation of L2 norm for:
556  * 1) difference between regularized pressure and analytical solution (using FunctionPython)
557  * 2) difference between RT velocities and analytical solution
558  * 3) difference of divergence
559  * */
560 
561 struct DiffData {
562  double pressure_error[2], velocity_error[2], div_error[2];
566 
567  double * solution;
568  const MH_DofHandler * dh;
570 
573 };
574 
575 template <int dim>
576 void l2_diff_local(ElementFullIter &ele, FEValues<dim,3> &fe_values, ExactSolution &anal_sol, DiffData &result) {
577 
578  fe_values.reinit(ele);
579  result.fe_values.update(ele,
580  result.data_->anisotropy,
581  result.data_->cross_section,
582  result.data_->conductivity);
583  double conductivity = result.data_->conductivity.value(ele->centre(), ele->element_accessor() );
584  double cross = result.data_->cross_section.value(ele->centre(), ele->element_accessor() );
585 
586 
587  // get coefficients on the current element
588  vector<double> fluxes(dim+1);
589  vector<double> pressure_traces(dim+1);
590 
591  for (unsigned int li = 0; li < ele->n_sides(); li++) {
592  fluxes[li] = result.dh->side_flux( *(ele->side( li ) ) );
593  pressure_traces[li] = result.dh->side_scalar( *(ele->side( li ) ) );
594  }
595  double pressure_mean = result.dh->element_scalar(ele);
596 
597  arma::vec analytical(5);
598  arma::vec3 flux_in_q_point;
599  arma::vec3 anal_flux;
600 
601  double velocity_diff=0, divergence_diff=0, pressure_diff=0, diff;
602 
603  // 1d: mean_x_squared = 1/6 (v0^2 + v1^2 + v0*v1)
604  // 2d: mean_x_squared = 1/12 (v0^2 + v1^2 +v2^2 + v0*v1 + v0*v2 + v1*v2)
605  double mean_x_squared=0;
606  for(unsigned int i_node=0; i_node < ele->n_nodes(); i_node++ )
607  for(unsigned int j_node=0; j_node < ele->n_nodes(); j_node++ )
608  {
609  mean_x_squared += (i_node == j_node ? 2.0 : 1.0) / ( 6 * dim ) // multiply by 2 on diagonal
610  * arma::dot( ele->node[i_node]->point(), ele->node[j_node]->point());
611  }
612 
613  for(unsigned int i_point=0; i_point < fe_values.n_points(); i_point++) {
614  arma::vec3 q_point = fe_values.point(i_point);
615 
616 
617  analytical = anal_sol.value(q_point, ele->element_accessor() );
618  for(unsigned int i=0; i< 3; i++) anal_flux[i] = analytical[i+1];
619 
620  // compute postprocesed pressure
621  diff = 0;
622  for(unsigned int i_shape=0; i_shape < ele->n_sides(); i_shape++) {
623  unsigned int oposite_node = (i_shape + dim) % (dim + 1);
624 
625  diff += fluxes[ i_shape ] *
626  ( arma::dot( q_point, q_point )/ 2
627  - mean_x_squared / 2
628  - arma::dot( q_point, ele->node[oposite_node]->point() )
629  + arma::dot( ele->centre(), ele->node[oposite_node]->point() )
630  );
631  }
632 
633  diff = - (1.0 / conductivity) * diff / dim / ele->measure() / cross + pressure_mean ;
634  diff = ( diff - analytical[0]);
635  pressure_diff += diff * diff * fe_values.JxW(i_point);
636 
637 
638  // velocity difference
639  flux_in_q_point.zeros();
640  for(unsigned int i_shape=0; i_shape < ele->n_sides(); i_shape++) {
641  flux_in_q_point += fluxes[ i_shape ]
642  * result.fe_values.RT0_value( ele, q_point, i_shape )
643  / cross;
644  }
645 
646  flux_in_q_point -= anal_flux;
647  velocity_diff += dot(flux_in_q_point, flux_in_q_point) * fe_values.JxW(i_point);
648 
649  // divergence diff
650  diff = 0;
651  for(unsigned int i_shape=0; i_shape < ele->n_sides(); i_shape++) diff += fluxes[ i_shape ];
652  diff = ( diff / ele->measure() / cross - analytical[4]);
653  divergence_diff += diff * diff * fe_values.JxW(i_point);
654 
655  }
656 
657 
658  result.velocity_diff[ele.index()] = velocity_diff;
659  result.velocity_error[dim-1] += velocity_diff;
660 
661  result.pressure_diff[ele.index()] = pressure_diff;
662  result.pressure_error[dim-1] += pressure_diff;
663 
664  result.div_diff[ele.index()] = divergence_diff;
665  result.div_error[dim-1] += divergence_diff;
666 
667 }
668 
669 
670 
671 
672 
673 
675  DBGMSG("l2 norm output\n");
676  ofstream os( FilePath("solution_error", FilePath::output_file) );
677 
678  const unsigned int order = 4; // order of Gauss quadrature
679 
680  // we create trivial Dofhandler , for P0 elements, to get access to, FEValues on individual elements
681  // this we use to integrate our own functions - difference of postprocessed pressure and analytical solution
682  FE_P_disc<0,1,3> fe_1d;
683  FE_P_disc<0,2,3> fe_2d;
684 
685  QGauss<1> quad_1d( order );
686  QGauss<2> quad_2d( order );
687 
688  MappingP1<1,3> mapp_1d;
689  MappingP1<2,3> mapp_2d;
690 
691  FEValues<1,3> fe_values_1d(mapp_1d, quad_1d, fe_1d, update_JxW_values | update_quadrature_points);
692  FEValues<2,3> fe_values_2d(mapp_2d, quad_2d, fe_2d, update_JxW_values | update_quadrature_points);
693 
694  FilePath source_file( "analytical_module.py", FilePath::input_file);
695  ExactSolution anal_sol_1d(5); // components: pressure, flux vector 3d, divergence
696  anal_sol_1d.set_python_field_from_file( source_file, "all_values_1d");
697 
698  ExactSolution anal_sol_2d(5);
699  anal_sol_2d.set_python_field_from_file( source_file, "all_values_2d");
700 
701 
702  static DiffData result;
703 
704  result.pressure_diff.resize( mesh_->n_elements() );
705  result.velocity_diff.resize( mesh_->n_elements() );
706  result.div_diff.resize( mesh_->n_elements() );
707 
708  result.pressure_error[0] = 0;
709  result.velocity_error[0] = 0;
710  result.div_error[0] = 0;
711  result.pressure_error[1] = 0;
712  result.velocity_error[1] = 0;
713  result.div_error[1] = 0;
714 
715 
716  auto vel_diff_ptr = std::make_shared< FieldElementwise<3, FieldValue<3>::Scalar> >(&(result.velocity_diff[0]), 1, mesh_->n_elements());
718  auto pressure_diff_ptr = std::make_shared< FieldElementwise<3, FieldValue<3>::Scalar> >(&(result.pressure_diff[0]), 1, mesh_->n_elements());
719  output_fields.pressure_diff.set_field(mesh_->region_db().get_region_set("ALL"), pressure_diff_ptr, 0);
720  auto div_diff_ptr = std::make_shared< FieldElementwise<3, FieldValue<3>::Scalar> >(&(result.div_diff[0]), 1, mesh_->n_elements());
721  output_fields.div_diff.set_field(mesh_->region_db().get_region_set("ALL"), div_diff_ptr, 0);
722 
724 
725  unsigned int solution_size;
726  darcy_flow->get_solution_vector(result.solution, solution_size);
727 
728  result.dh = &( darcy_flow->get_mh_dofhandler());
729  result.darcy = darcy_flow;
730  result.data_ = &(darcy_flow->data_);
731 
732  FOR_ELEMENTS( mesh_, ele) {
733 
734  switch (ele->dim()) {
735  case 1:
736 
737  l2_diff_local<1>( ele, fe_values_1d, anal_sol_1d, result);
738  break;
739  case 2:
740  l2_diff_local<2>( ele, fe_values_2d, anal_sol_2d, result);
741  break;
742  }
743  }
744 
745  os << "l2 norm output\n\n"
746  << "pressure error 1d: " << sqrt(result.pressure_error[0]) << endl
747  << "pressure error 2d: " << sqrt(result.pressure_error[1]) << endl
748  << "velocity error 1d: " << sqrt(result.velocity_error[0]) << endl
749  << "velocity error 2d: " << sqrt(result.velocity_error[1]) << endl
750  << "div error 1d: " << sqrt(result.div_error[0]) << endl
751  << "div error 2d: " << sqrt(result.div_error[1]);
752 }
753 
FieldSet & data()
Definition: equation.hh:188
const MH_DofHandler * dh
void set_python_field_from_file(const FilePath &file_name, const string &func_name)
Field< 3, FieldValue< 3 >::VectorFixed > field_ele_flux
vector< double > ele_piezo_head
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
Field< 3, FieldValue< 3 >::Scalar > velocity_diff
void set_limit_side(LimitSide side)
Definition: field_set.hh:171
#define DBGMSG(...)
Definition: global_defs.h:196
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
vector< double > div_diff
Output class for darcy_flow_mh model.
DarcyFlowMH_Steady * darcy_flow
#define FOR_ELEMENT_NODES(i, j)
Definition: elements.h:150
virtual void get_solution_vector(double *&vec, unsigned int &vec_size)
const arma::vec::fixed< spacedim > point(const unsigned int point_no)
Return coordinates of the quadrature point in the actual cell system.
Definition: fe_values.cc:184
Header: The functions for all outputs.
Accessor to input data conforming to declared Array.
Definition: accessors.hh:521
Definition: system.hh:72
double getY() const
Definition: nodes.hh:71
static Input::Type::Record input_type
The specification of output stream.
Definition: output_time.hh:57
Definition: nodes.hh:44
unsigned int bulk_size() const
Definition: region.cc:252
static Input::Type::Record input_type
Field< 3, FieldValue< 3 >::Scalar > field_node_pressure
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:357
Class for declaration of the input of type Bool.
Definition: type_base.hh:321
MappingP1< 1, 3 > map1
int xfclose(FILE *stream)
FCLOSE WITH ERROR HANDLING.
Definition: xio.cc:309
DarcyFlowMHOutput(DarcyFlowMH_Steady *flow, Input::Record in_rec)
const double JxW(const unsigned int point_no)
Return the product of Jacobian determinant and the quadrature weight at given quadrature point...
Definition: fe_values.cc:178
DOFHandlerMultiDim * dh
static Default obligatory()
Definition: type_record.hh:87
Selection & copy_values(const Selection &sel)
int xfprintf(FILE *out, const char *fmt,...)
FPRINTF WITH ERROR HANDLING.
Definition: xio.cc:395
RegionSet get_region_set(const string &set_name) const
Definition: region.cc:361
void distribute_dofs(FiniteElement< 1, 3 > &fe1d, FiniteElement< 2, 3 > &fe2d, FiniteElement< 3, 3 > &fe3d, const unsigned int offset=0)
Distributes degrees of freedom on the mesh needed for the given finite elements.
Definition: dofhandler.cc:257
void make_corner_scalar(vector< double > &node_scalar)
Class FEValues calculates finite element data on the actual cells such as shape function values...
int index() const
Definition: sys_vector.hh:88
bool is_current(const TimeMark::Type &mask) const
FieldPython< 3, FieldValue< 3 >::Vector > ExactSolution
const RegionDB & region_db() const
Definition: mesh.h:148
const MH_DofHandler & get_mh_dofhandler()
Field< 3, FieldValue< 3 >::Integer > subdomain
double t() const
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Partitioning * get_part()
Definition: mesh.cc:162
unsigned int n_sides()
Definition: mesh.cc:151
static TimeMarks & marks()
Class for declaration of inputs sequences.
Definition: type_base.hh:230
double div_error[2]
FiniteElement< dim, 3 > * fe() const
Symmetric Gauss-Legendre quadrature formulae on simplices.
const unsigned int n_points()
Returns the number of quadrature points.
Definition: fe_values.cc:202
DarcyFlowMH_Steady * darcy
unsigned int boundary_idx() const
Returns index of the region in the boundary set.
Definition: region.hh:75
double getZ() const
Definition: nodes.hh:73
unsigned int size() const
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:401
static Default optional()
Definition: type_record.hh:100
Data for Darcy flow equation.
bool opt_val(const string &key, Ret &value) const
Discontinuous Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:213
Field< 3, FieldValue< 3 >::Scalar > field_ele_pressure
Transformed quadrature points.
Global macros to enhance readability and debugging, general constants.
unsigned int n_elements() const
Definition: mesh.h:137
FE_P_disc< 1, 2, 3 > fe2
static OutputTime * create_output_stream(const Input::Record &in_rec)
This method write all registered data to output streams.
Definition: output.cc:171
double element_scalar(ElementFullIter &ele) const
temporary replacement for DofHandler accessor, scalar (pressure) on element
double pressure_error[2]
void update(ElementFullIter ele, FieldType &cond_anisothropy, FieldType_Scalar &cross_section, FieldType_Scalar &conductivity)
Definition: mh_fe_values.cc:34
MappingP1< 2, 3 > map2
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Field< 3, FieldValue< 3 >::TensorFixed > anisotropy
FILE * raw_output_file
Raw data output file.
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
double getX() const
Definition: nodes.hh:69
#define START_TIMER(tag)
Starts a timer with specified tag.
Provides the numbering of the finite element degrees of freedom on the computational mesh...
Definition: dofhandler.hh:251
double velocity_error[2]
MHFEValues fe_values
unsigned int index(const T *pointer) const
Definition: sys_vector.hh:383
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:399
FILE * balance_output_file
Temporary solution for writing balance into separate file.
vector< double > ele_pressure
vector< double > velocity_diff
Input::Record in_rec_
Accessor to the input record for the DarcyFlow output.
vector< double > subdomains
void mark_output_times(const TimeGovernor &tg)
Definition: output.cc:331
void set_time(const TimeGovernor &time)
Definition: field_set.hh:186
static Input::Type::Selection output_selection
MappingP1< 3, 3 > map3
#define MPI_Comm_rank
Definition: mpi.h:236
Dedicated class for storing path to input and output files.
Definition: file_path.hh:32
vector< int > & seq_output_partition()
Field< 3, FieldValue< 3 >::Scalar > field_ele_piezo_head
void write_time_frame()
Definition: output.cc:362
Field< 3, FieldValue< 3 >::Scalar > conductivity
double side_flux(const Side &side) const
temporary replacement for DofHandler accessor, flux through given side
arma::vec3 RT0_value(ElementFullIter ele, arma::vec3 point, unsigned int face)
Definition: mh_fe_values.cc:75
Field< 3, FieldValue< 3 >::Scalar > pressure_diff
void output(OutputTime *stream)
Definition: field_set.cc:136
const Selection & close() const
unsigned int boundary_size() const
Definition: region.cc:245
static FileName output()
Definition: type_base.hh:449
void get_dof_indices(const CellIterator &cell, unsigned int indices[]) const override
Returns the global indices of dofs associated to the cell.
Definition: dofhandler.cc:346
void add_admissible_field_names(const Input::Array &in_array, const Input::Type::Selection &in_sel)
Registers names of output fields that can be written using this stream.
Definition: output.cc:231
TimeGovernor const & time()
Definition: equation.hh:143
void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0)
Definition: field.impl.hh:197
void reinit(ElementFullIter &cell)
Update cell-dependent data (gradients, Jacobians etc.)
Definition: fe_values.cc:244
#define FOR_BOUNDARIES(_mesh_, i)
Definition: mesh.h:375
Mixed-hybrid of steady Darcy flow with sources and variable density.
Input::Type::Selection make_output_field_selection(const string &name, const string &desc="")
Definition: field_set.cc:69
Definitions of particular quadrature rules on simplices.
FieldCommon & name(const string &name)
Definition: field_common.hh:71
#define MPI_COMM_WORLD
Definition: mpi.h:123
Calculates finite element data on the actual cell.
Definition: fe_values.hh:370
Field< 3, FieldValue< 3 >::Scalar > div_diff
FE_P_disc< 1, 3, 3 > fe3
unsigned int n_nodes() const
Definition: mesh.h:133
vector< double > corner_pressure
mixed-hybrid model of linear Darcy flow, possibly unsteady.
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:157
Record type proxy class.
Definition: type_record.hh:161
Field< 3, FieldValue< 3 >::Scalar > cross_section
DarcyFlowMH_Steady::EqData * data_
bool is_valid() const
Returns false if the region has undefined/invalid value.
Definition: region.hh:67
double side_scalar(const Side &side) const
temporary replacement for DofHandler accessor, scalar (pressure) on edge of the side ...
Class for representation SI units of Fields.
Definition: unit_si.hh:31
FE_P_disc< 1, 1, 3 > fe1
void l2_diff_local(ElementFullIter &ele, FEValues< dim, 3 > &fe_values, ExactSolution &anal_sol, DiffData &result)
vector< double > ele_flux
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:44
#define FOR_SIDES(_mesh_, it)
Definition: mesh.h:401
void make_node_scalar_param()
Calculate nodes scalar, store it in double* node_scalars instead of node->scalar. ...
Template for classes storing finite set of named values.
const unsigned int n_global_dofs() const
Getter for the number of all mesh dofs required by the given finite element.
Definition: dofhandler.hh:72
Field< 3, FieldValue< 3 >::Scalar > water_source_density
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
FieldCommon & output_type(OutputTime::DiscreteSpace rt)
vector< double > pressure_diff
NodeVector node_vector
Vector of nodes of the mesh.
Definition: mesh.h:196
FILE * xfopen(const std::string &fname, const char *mode)
Definition: xio.cc:246
void output()
Calculate values for output.
Transformed quadrature weights.
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386