Flow123d  master-f44eb46
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/pybind11.h>
27 #include <pybind11/eval.h>
28 #include <pybind11/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 template <int spacedim, class Value>
108  required_fields_.clear();
109 
110  auto used_fields_array = in_rec_.val<Input::Array>("used_fields");
111  std::vector<std::string> used_fields_vec;
112  used_fields_array.copy_to(used_fields_vec);
113  for(auto field_name : used_fields_vec) {
114  auto field_ptr = field_set.field(field_name);
115  if (field_ptr != nullptr) required_fields_.push_back( field_ptr );
116  else THROW( FieldSet::ExcUnknownField() << FieldCommon::EI_Field(field_name) << FieldSet::EI_FieldType("python declaration") << Input::EI_Address( in_rec_.address_string() ) );
117  }
118 
119  // instance of FieldCommon of this field (see cache_reinit method)
120  self_field_ptr_ = field_set.field(this->field_name_);
121 
122  return required_fields_;
123 }
124 
125 
126 
127 template <int spacedim, class Value>
129 {
130  std::vector<FieldCacheProxy> field_data;
131  for (auto field_ptr : required_fields_) {
132  std::string field_name = field_ptr->name();
133  double * cache_data = field_ptr->value_cache()->data_;
134  field_data.emplace_back(field_name, field_ptr->shape_, cache_data, CacheMapElementNumber::get()*field_ptr->n_shape());
135  }
136 
137  double * cache_data = self_field_ptr_->value_cache()->data_;
138  FieldCacheProxy result_data(this->field_name_, self_field_ptr_->shape_, cache_data, (CacheMapElementNumber::get()*self_field_ptr_->n_shape()));
139 
140  try {
141  py::object p_func = user_class_instance_.attr("_cache_reinit");
142  p_func(this->time_.end(), field_data, result_data);
143  } catch (const py::error_already_set &ex) {
145  }
146 }
147 
148 
149 
150 template <int spacedim, class Value>
152  ElementCacheMap &cache_map, unsigned int region_patch_idx)
153 {
154  unsigned int reg_chunk_begin = cache_map.region_chunk_begin(region_patch_idx);
155  unsigned int reg_chunk_end = cache_map.region_chunk_end(region_patch_idx);
156  try {
157  py::object p_func = user_class_instance_.attr("_cache_update");
158  p_func(this->field_name_, reg_chunk_begin, reg_chunk_end);
159  } catch (const py::error_already_set &ex) {
161  }
162 }
163 
164 
165 
166 template <int spacedim, class Value>
168 
169 
170 #endif /* FIELD_PYTHON_IMPL_HH_ */
static unsigned int get()
Return number of stored elements.
Directing class of FieldValueCache.
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Helper class, holds data of one field.
static const Input::Type::Record & get_input_type()
Implementation.
FieldPython(unsigned int n_comp=0)
void set_python_field_from_class(const string &file_name, const string &class_name)
void cache_reinit(const ElementCacheMap &cache_map) override
void cache_update(FieldValueCache< typename Value::element_type > &data_cache, ElementCacheMap &cache_map, unsigned int region_patch_idx) override
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
virtual ~FieldPython()
std::vector< const FieldCommon * > set_dependency(FieldSet &field_set) override
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:173
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
const Ret val(const string &key) const
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
Record type proxy class.
Definition: type_record.hh:182
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
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
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
@ Value
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:104
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:63
void throw_error(spirit_namespace::position_iterator< Iter_type > i, const std::string &reason)
#define FMT_UNUSED
Definition: posix.h:75
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.