Flow123d
field_interpolated_p0_impl.hh
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: function_interpolated_p0.cc 1567 2012-02-28 13:24:58Z jan.brezina $
21  * $Revision: 1567 $
22  * $LastChangedBy: jan.brezina $
23  * $LastChangedDate: 2012-02-28 14:24:58 +0100 (Tue, 28 Feb 2012) $
24  *
25  *
26  */
27 
28 
29 #ifndef FIELD_INTERPOLATED_P0_IMPL_HH_
30 #define FIELD_INTERPOLATED_P0_IMPL_HH_
31 
32 #include "field_interpolated_p0.hh"
33 #include "system/system.hh"
34 #include "mesh/msh_gmshreader.h"
35 #include "mesh/bih_tree.hh"
37 #include "mesh/ngh/include/point.h"
38 #include "system/sys_profiler.hh"
39 //#include "boost/lexical_cast.hpp"
40 //#include "system/tokenizer.hh"
41 //#include "system/xio.h"
42 
43 
44 namespace it = Input::Type;
45 /*template <int spacedim, class Value>
46 it::Record FieldInterpolatedP0<spacedim, Value>::input_type
47  = it::Record("FieldInterpolatedP0", "Field given by P0 data on another mesh. Currently defined only on boundary.")
48  .derive_from(FieldBase<spacedim, Value>::input_type)
49  // TODO: use mesh record here, but make it possibly of the same simplicity (the file name only)
50  .declare_key("mesh", it::FileName::input(),it::Default::obligatory(),
51  "File with the mesh from which we interpolate. (currently only GMSH supported)")
52  // TODO: allow interpolation from VTK files (contains also mesh), and our own format of raw data, that includes:
53  // mesh, dof_handler, and dof values
54  .declare_key("raw_data", it::FileName::input(), it::Default::obligatory(),
55  "File with raw output from flow calculation. Currently we can interpolate only pressure."); */
56 
57 template <int spacedim, class Value>
60 
61 
62 template <int spacedim, class Value>
64  Input::Type::AbstractRecord &a_type, const typename Value::ElementInputType *eit
65  )
66 {
67  it::Record type=
68  it::Record("FieldInterpolatedP0", FieldBase<spacedim,Value>::template_name()+" Field constant in space.")
69  .derive_from(a_type)
71  "Input file with ASCII GMSH file format.")
73  "The values of the Field are read from the $ElementData section with field name given by this key.")
74  .close();
75 
76  return type;
77 }
78 
79 
80 template <int spacedim, class Value>
82 : FieldBase<spacedim, Value>(n_comp)
83 {}
84 
85 
86 
87 
88 template <int spacedim, class Value>
90 
91  // read mesh, create tree
92  {
93  source_mesh_ = new Mesh();
94  reader_ = new GmshMeshReader( rec.val<FilePath>("gmsh_file") );
95  reader_->read_mesh( source_mesh_ );
96  // no call to mesh->setup_topology, we need only elements, no connectivity
97  }
98  bih_tree_ = new BIHTree( source_mesh_ );
99 
100  // allocate data_
101  unsigned int data_size = source_mesh_->element.size() * (this->value_.n_rows() * this->value_.n_cols());
102  data_ = new double[data_size];
103  std::fill(data_, data_ + data_size, 0.0);
104 
105  field_name_ = rec.val<std::string>("field_name");
106 }
107 
108 
109 
110 /**
111  * TODO:
112  * nahradit pressure_ -> value_
113  *
114  * for(unsigned int i=0; i < value_.n_rows(); i ++)
115  * for( ... n_cols() )
116  * value_.at(i,j) = 0.0;
117  *
118  * Value tmp_value;
119  * Value::from_raw(tmp_value, (typename Value::element_type *)(data_+idx));
120  * for(unsigned int i=0; i < value_.n_rows(); i ++)
121  * for( ... n_cols() )
122  * value_.at(i,j) += measure * tmp_value.at(i,j);
123  *
124  * ?? spojit caluculate_abscissa a calculate_triangle
125  */
126 
127 
128 
129 template <int spacedim, class Value>
131  ASSERT(( ele->dim() == 3 ), "Dimension of element must be 3!\n");
132 
133  te.SetPoints(TPoint(ele->node[0]->point()(0), ele->node[0]->point()(1), ele->node[0]->point()(2)),
134  TPoint(ele->node[1]->point()(0), ele->node[1]->point()(1), ele->node[1]->point()(2)),
135  TPoint(ele->node[2]->point()(0), ele->node[2]->point()(1), ele->node[2]->point()(2)),
136  TPoint(ele->node[3]->point()(0), ele->node[3]->point()(1), ele->node[3]->point()(2)) );
137 }
138 
139 
140 
141 template <int spacedim, class Value>
143  ASSERT(( ele->dim() == 2 ), "Dimension of element must be 2!\n");
144 
145  tr.SetPoints(TPoint(ele->node[0]->point()(0), ele->node[0]->point()(1), ele->node[0]->point()(2)),
146  TPoint(ele->node[1]->point()(0), ele->node[1]->point()(1), ele->node[1]->point()(2)),
147  TPoint(ele->node[2]->point()(0), ele->node[2]->point()(1), ele->node[2]->point()(2)) );
148 }
149 
150 
151 
152 template <int spacedim, class Value>
154  ASSERT(( ele->dim() == 1 ), "Dimension of element must be 1!\n");
155 
156  ab.SetPoints(TPoint(ele->node[0]->point()(0), ele->node[0]->point()(1), ele->node[0]->point()(2)),
157  TPoint(ele->node[1]->point()(0), ele->node[1]->point()(1), ele->node[1]->point()(2)) );
158 }
159 
160 
161 
162 template <int spacedim, class Value>
164  ASSERT(( ele->dim() == 0 ), "Dimension of element must be 0!\n");
165 
166  p.SetCoord( ele->node[0]->point()(0), ele->node[0]->point()(1), ele->node[0]->point()(2) );
167 }
168 
169 
170 
171 template <int spacedim, class Value>
173  ASSERT(source_mesh_, "Null mesh pointer of elementwise field: %s, did you call init_from_input(Input::Record)?\n", field_name_.c_str());
174  ASSERT(data_, "Null data pointer.\n");
175  if (reader_ == NULL) return false;
176 
177  //walkaround for the steady time governor - there is no data to be read in time==infinity
178  //TODO: is it possible to check this before calling set_time?
179  if (time == numeric_limits< double >::infinity()) return false;
180 
181  GMSH_DataHeader search_header;
182  search_header.actual = false;
183  search_header.field_name = field_name_;
184  search_header.n_components = this->value_.n_rows() * this->value_.n_cols();
185  search_header.n_entities = source_mesh_->element.size();
186  search_header.time = time;
187 
188  bool boundary_domain_ = false;
189  //DBGMSG("reading data for interpolation: name: %s \t time: %f \t n: %d\n", field_name_.c_str(), time, source_mesh_->element.size());
190  reader_->read_element_data(search_header, data_, source_mesh_->elements_id_maps(boundary_domain_) );
191  //DBGMSG("end of reading data for interpolation: %s\n", field_name_.c_str());
192 
193  return search_header.actual;
194 }
195 
196 
197 
198 template <int spacedim, class Value>
199 typename Value::return_type const &FieldInterpolatedP0<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
200 {
201  ASSERT( elm.is_elemental(), "FieldInterpolatedP0 works only for 'elemental' ElementAccessors.\n");
202  if (elm.idx() != computed_elm_idx_) {
203  computed_elm_idx_ = elm.idx();
204 
205  if (elm.dim() == 3) {
206  xprintf(Err, "Dimension of element in target mesh must be 0, 1 or 2! elm.idx() = %d\n", elm.idx());
207  }
208 
209  double epsilon = 4* numeric_limits<double>::epsilon() * elm.element()->measure();
210 
211  // gets suspect elements
212  if (elm.dim() == 0) {
213  //Point point;
214  //for (unsigned int i=0; i<3; i++) point(i) = elm.element()->node[0]->point()(i);
215  searched_elements_.clear();
216  ((BIHTree *)bih_tree_)->find_point(elm.element()->node[0]->point(), searched_elements_);
217  } else {
218  BoundingBox bb;
219  elm.element()->get_bounding_box(bb);
220  searched_elements_.clear();
221  ((BIHTree *)bih_tree_)->find_bounding_box(bb, searched_elements_);
222  }
223 
224  // set zero values of value_ object
225  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
226  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
227  this->value_(i,j) = 0.0;
228  }
229  }
230 
231  double total_measure=0.0, measure;
232  TIntersectionType iType;
233 
234  START_TIMER("compute_pressure");
235  ADD_CALLS(searched_elements_.size());
236  for (std::vector<unsigned int>::iterator it = searched_elements_.begin(); it!=searched_elements_.end(); it++)
237  {
238  ElementFullIter ele = source_mesh_->element( *it );
239  if (ele->dim() == 3) {
240  create_tetrahedron(ele, tetrahedron_);
241  // get intersection (set measure = 0 if intersection doesn't exist)
242  switch (elm.dim()) {
243  case 0: {
244  create_point(elm.element(), point_);
245  if ( tetrahedron_.IsInner(point_) ) {
246  measure = 1.0;
247  } else {
248  measure = 0.0;
249  }
250  break;
251  }
252  case 1: {
253  create_abscissa(elm.element(), abscissa_);
254  GetIntersection(abscissa_, tetrahedron_, iType, measure);
255  if (iType != line) {
256  measure = 0.0;
257  }
258  break;
259  }
260  case 2: {
261  create_triangle(elm.element(), triangle_);
262  GetIntersection(triangle_, tetrahedron_, iType, measure);
263  if (iType != area) {
264  measure = 0.0;
265  }
266  break;
267  }
268  }
269 
270 
271 
272  //adds values to value_ object if intersection exists
273  if (measure > epsilon) {
274  unsigned int index = this->value_.n_rows() * this->value_.n_cols() * (*it);
275  typename Value::element_type * ele_data_ptr = (typename Value::element_type *)(data_+index);
276  typename Value::return_type & ret_type_value = const_cast<typename Value::return_type &>( Value::from_raw(this->r_value_, ele_data_ptr) );
277  Value tmp_value = Value( ret_type_value );
278 
279  /*cout << "n_rows, n_cols = " << tmp_value.n_rows() << ", " << tmp_value.n_cols() << endl;
280  for (unsigned int i=0; i < tmp_value.n_rows(); i++) {
281  for (unsigned int j=0; j < tmp_value.n_cols(); j++) {
282  cout << "(" << i << "," << j << ") = " << tmp_value(i,j) << ", ";
283  }
284  cout << endl;
285  }
286  cout << endl;*/
287 
288  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
289  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
290  this->value_(i,j) += tmp_value(i,j) * measure;
291  }
292  }
293  total_measure += measure;
294  }
295  } else {
296  xprintf(Err, "Dimension of element in source mesh must be 3!\n");
297  }
298  }
299 
300  // computes weighted average
301  if (total_measure > epsilon) {
302  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
303  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
304  this->value_(i,j) /= total_measure;
305  }
306  }
307  } else {
308  xprintf(Warn, "Processed element with idx %d is out of source mesh!\n", elm.idx());
309  }
310  END_TIMER("compute_pressure");
311 
312  }
313  return this->r_value_;
314 }
315 
316 
317 
318 template <int spacedim, class Value>
321 {
322  ASSERT( elm.is_elemental(), "FieldInterpolatedP0 works only for 'elemental' ElementAccessors.\n");
323  xprintf(Err, "Not implemented.");
324  // not supported yet
325 }
326 
327 
328 
329 
330 
331 #endif