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