Flow123d  JB_transport-9331eee
field_python.impl.hh
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 field_python.impl.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_PYTHON_IMPL_HH_
19 #define FIELD_PYTHON_IMPL_HH_
20 
21 
22 #include <type_traits>
23 #include "fields/field_python.hh"
24 #include "fields/field_set.hh"
25 #include "fields/python_field_proxy.hh" // TODO check if include is necessary
26 #include <pybind11.h>
27 #include <eval.h>
28 #include <stl.h>
29 
30 namespace py = pybind11;
31 
32 /// Implementation.
33 
34 namespace it = Input::Type;
35 
36 FLOW123D_FORCE_LINK_IN_CHILD(field_python)
37 
38 
39 
40 template <int spacedim, class Value>
42 {
43  return it::Record("FieldPython", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field given by a Python script.")
46  .declare_key("source_file", it::String(), it::Default::obligatory(),
47  "Python script given as external file in format 'dir'.'file_name' without .py extension")
49  "Function in the given script that returns tuple containing components of the return type.\n"
50  "For NxM tensor values: tensor(row,col) = tuple( M*row + col ).")
51  .declare_key("used_fields", it::Array(it::String()), it::Default("[]"),
52  "Defines list of fields necessary in evaluation of actual field.")
53  //.declare_key("units", FieldAlgorithmBase<spacedim, Value>::get_field_algo_common_keys(), it::Default::optional(),
54  // "Definition of unit.")
55  .close();
56 }
57 
58 
59 template <int spacedim, class Value>
61  Input::register_class< FieldPython<spacedim, Value>, unsigned int >("FieldPython") +
63 
64 
65 
66 template <int spacedim, class Value>
68 : FieldAlgorithmBase<spacedim, Value>( n_comp)
69 {
70  this->is_constant_in_space_ = false;
71 }
72 
73 
74 
75 
76 template <int spacedim, class Value>
78  this->init_unit_conversion_coefficient(rec, init_data);
79  this->field_name_ = init_data.field_name_;
80 
81  std::string source_file = rec.val<string>("source_file");
82  std::string source_class = rec.val<string>("class");
83  try {
84  set_python_field_from_class( source_file, source_class );
85  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, rec)
86 
87  in_rec_ = rec;
88 }
89 
90 
91 
92 template <int spacedim, class Value>
93 void FieldPython<spacedim, Value>::set_python_field_from_class(const string &file_name, const string &class_name)
94 {
95  py::module_ flowpy_module = PythonLoader::load_module_by_name("flowpy");
96  py::module_ class_module = PythonLoader::load_module_from_file( string(file_name) );
97  try {
98  user_class_instance_ = flowpy_module.attr("PythonFieldBase").attr("_create")(class_module, class_name.c_str());
99  } catch (const py::error_already_set &ex) {
101  }
102 }
103 
104 
105 
106 /**
107  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
108  */
109 template <int spacedim, class Value>
110 typename Value::return_type const & FieldPython<spacedim, Value>::value(FMT_UNUSED const Point &p, FMT_UNUSED const ElementAccessor<spacedim> &elm)
111 {
112  ASSERT(false).warning("Method FieldPython::value is obsolete. DO not use it!\n");
113  return this->r_value_;
114 }
115 
116 
117 /**
118  * Returns std::vector of scalar values in several points at once.
119  */
120 template <int spacedim, class Value>
123 {
124  ASSERT(false).warning("Method FieldPython::value_list is obsolete. DO not use it!\n");
125 }
126 
127 
128 
129 template <int spacedim, class Value>
131  required_fields_.clear();
132 
133  auto used_fields_array = in_rec_.val<Input::Array>("used_fields");
134  std::vector<std::string> used_fields_vec;
135  used_fields_array.copy_to(used_fields_vec);
136  for(auto field_name : used_fields_vec) {
137  auto field_ptr = field_set.field(field_name);
138  if (field_ptr != nullptr) required_fields_.push_back( field_ptr );
139  else THROW( FieldSet::ExcUnknownField() << FieldCommon::EI_Field(field_name) << FieldSet::EI_FieldType("python declaration") << Input::EI_Address( in_rec_.address_string() ) );
140  }
141 
142  // instance of FieldCommon of this field (see cache_reinit method)
143  self_field_ptr_ = field_set.field(this->field_name_);
144 
145  return required_fields_;
146 }
147 
148 
149 
150 template <int spacedim, class Value>
152 {
153  std::vector<FieldCacheProxy> field_data;
154  for (auto field_ptr : required_fields_) {
155  std::string field_name = field_ptr->name();
156  double * cache_data = field_ptr->value_cache()->data_;
157  field_data.emplace_back(field_name, field_ptr->shape_, cache_data, CacheMapElementNumber::get()*field_ptr->n_shape());
158  }
159 
160  double * cache_data = self_field_ptr_->value_cache()->data_;
161  FieldCacheProxy result_data(this->field_name_, self_field_ptr_->shape_, cache_data, (CacheMapElementNumber::get()*self_field_ptr_->n_shape()));
162 
163  try {
164  py::object p_func = user_class_instance_.attr("_cache_reinit");
165  p_func(this->time_.end(), field_data, result_data);
166  } catch (const py::error_already_set &ex) {
168  }
169 }
170 
171 
172 
173 template <int spacedim, class Value>
175  ElementCacheMap &cache_map, unsigned int region_patch_idx)
176 {
177  unsigned int reg_chunk_begin = cache_map.region_chunk_begin(region_patch_idx);
178  unsigned int reg_chunk_end = cache_map.region_chunk_end(region_patch_idx);
179  try {
180  py::object p_func = user_class_instance_.attr("_cache_update");
181  p_func(this->field_name_, reg_chunk_begin, reg_chunk_end);
182  } catch (const py::error_already_set &ex) {
184  }
185 }
186 
187 
188 
189 template <int spacedim, class Value>
191 
192 
193 #endif /* FIELD_PYTHON_IMPL_HH_ */
CacheMapElementNumber::get
static unsigned int get()
Return number of stored elements.
Definition: field_value_cache.hh:94
FieldPython::init_from_input
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Definition: field_python.impl.hh:77
FieldPython::set_python_field_from_class
void set_python_field_from_class(const string &file_name, const string &class_name)
Definition: field_python.impl.hh:93
FieldAlgoBaseInitData::field_name_
std::string field_name_
Definition: field_algo_base.hh:91
field_python.hh
ASSERT
#define ASSERT(expr)
Definition: asserts.hh:351
FieldPython::set_dependency
std::vector< const FieldCommon * > set_dependency(FieldSet &field_set) override
Definition: field_python.impl.hh:130
ElementCacheMap
Directing class of FieldValueCache.
Definition: field_value_cache.hh:152
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
field_set.hh
FLOW123D_FORCE_LINK_IN_CHILD
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:104
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
FieldAlgorithmBase::is_constant_in_space_
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Definition: field_algo_base.hh:289
std::vector
Definition: doxy_dummy_defs.hh:7
ElementAccessor
Definition: dh_cell_accessor.hh:32
FieldPython::cache_reinit
void cache_reinit(const ElementCacheMap &cache_map) override
Definition: field_python.impl.hh:151
FieldAlgorithmBase::Point
Space< spacedim >::Point Point
Definition: field_algo_base.hh:115
ElementCacheMap::region_chunk_end
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
Definition: field_value_cache.hh:273
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Input::Type::Record::derive_from
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
FieldPython::get_input_type
static const Input::Type::Record & get_input_type()
Implementation.
Definition: field_python.impl.hh:41
FieldCacheProxy
Helper class, holds data of one field.
Definition: python_field_proxy.hh:31
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
FieldAlgoBaseInitData
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
Definition: field_algo_base.hh:81
INPUT_CATCH
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:63
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
Input::Type::Record::declare_key
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:503
FieldPython::FieldPython
FieldPython(unsigned int n_comp=0)
Definition: field_python.impl.hh:67
FieldSet
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
PythonLoader::throw_error
static void throw_error(const pybind11::error_already_set &ex)
Definition: python_loader.cc:93
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Input::Type
Definition: balance.hh:41
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
Value
@ Value
Definition: finite_element.hh:43
FieldPython::cache_update
void cache_update(FieldValueCache< typename Value::element_type > &data_cache, ElementCacheMap &cache_map, unsigned int region_patch_idx) override
Definition: field_python.impl.hh:174
ElementCacheMap::region_chunk_begin
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
Definition: field_value_cache.hh:267
FieldPython
Definition: field_python.hh:52
Input::Type::Record::copy_keys
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
FieldAlgorithmBase
Definition: field_algo_base.hh:112
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Input::Type::String
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
PythonLoader::load_module_by_name
static pybind11::module_ load_module_by_name(const std::string &module_name)
Definition: python_loader.cc:78
Armor::Array< double >
FieldPython::value
virtual const Value::return_type & value(const Point &p, const ElementAccessor< spacedim > &elm)
Definition: field_python.impl.hh:110
python_field_proxy.hh
FieldPython::value_list
virtual void value_list(const Armor::array &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
Definition: field_python.impl.hh:121
FieldPython::~FieldPython
virtual ~FieldPython()
Definition: field_python.impl.hh:190
PythonLoader::load_module_from_file
static pybind11::module_ load_module_from_file(const std::string &fname)
Definition: python_loader.cc:41
FieldSet::field
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:171
FMT_UNUSED
#define FMT_UNUSED
Definition: posix.h:75