00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef FEM_FEMKERNEL_H
00010 #define FEM_FEMKERNEL_H
00011
00012 #include <core/imaging2.hpp>
00013 #include <core/matrix_utilities.hpp>
00014
00015 namespace imaging
00016 {
00017
00018 template<class fem_types> class Grid;
00019
00020 template<std::size_t M, std::size_t N>
00021 float_t transform_det(const ublas::fixed_matrix<float_t, M, N> & derivative)
00022 {
00023 return fabs(determinant(derivative));
00024 }
00025
00035 template<class fem_types>
00036 class FemKernel
00037 {
00038 private:
00039 static const std::size_t data_dimension = fem_types::data_dimension;
00040
00041 static const std::size_t n_element_nodes = fem_types::shape_function_t::n_element_nodes;
00042 static const std::size_t n_element_vertices = fem_types::transform_t::n_element_vertices;
00043
00044 typedef typename fem_types::shape_function_t shape_function_t;
00045
00046 typedef typename fem_types::transform_t transform_t;
00047 typedef typename fem_types::integrator_t integrator_t;
00048 typedef typename fem_types::boundary_integrator_t boundary_integrator_t;
00049
00050 ublas::fixed_vector< ublas::fixed_vector<float_t, n_element_nodes>, integrator_t::n_nodes> _shape_values;
00051 ublas::fixed_vector< ublas::fixed_vector< ublas::fixed_vector<float_t, data_dimension>, n_element_nodes >, integrator_t::n_nodes > _shape_gradients;
00052 ublas::fixed_vector<float_t, integrator_t::n_nodes> _transform_determinants;
00053
00054 ublas::fixed_vector< ublas::fixed_vector<float_t, n_element_nodes>, boundary_integrator_t::n_nodes > _shape_boundary_values;
00055 ublas::fixed_vector< ublas::fixed_vector<float_t, n_element_nodes>, boundary_integrator_t::n_nodes > _shape_boundary_derivatives;
00056 ublas::fixed_vector<float_t, boundary_integrator_t::n_nodes> _boundary_transform_determinants;
00057
00058 ublas::fixed_vector<float_t, data_dimension> _boundary_normal;
00059 ublas::fixed_vector< ublas::fixed_vector<float_t, data_dimension>, shape_function_t::n_shape_face_nodes > _boundary_normals_at_nodes;
00060
00061
00062 const Grid<fem_types> & _grid;
00063 std::size_t _current_element;
00064 std::size_t _current_boundary_element;
00065
00066 public:
00067
00069 FemKernel(const Grid<fem_types> & grid) : _grid(grid) {}
00070
00072 const Grid<fem_types> & grid() const { return _grid; };
00073
00079 void set_element(std::size_t element);
00080
00086 void set_boundary_element(std::size_t boundary_element);
00087
00090 void lazy_set_element(std::size_t element) { _current_element = element; }
00091
00093 float_t shape_value(std::size_t integrator_node, std::size_t element_node) const
00094 { return _shape_values(integrator_node)(element_node); }
00095
00097 const ublas::fixed_vector<float_t, fem_types::data_dimension> & shape_gradient(std::size_t integrator_node, std::size_t element_node) const
00098 { return _shape_gradients(integrator_node)(element_node); }
00099
00101 float_t transform_determinant(std::size_t integrator_node) const
00102 { return _transform_determinants(integrator_node); }
00103
00105 float_t shape_boundary_value(std::size_t integrator_node, std::size_t element_node) const
00106 { return _shape_boundary_values(integrator_node)(element_node); }
00107
00109 float_t shape_boundary_derivative(std::size_t integrator_node, std::size_t element_node) const
00110 { return _shape_boundary_derivatives(integrator_node)(element_node); }
00111
00113 float_t boundary_transform_determinant(std::size_t integrator_node) const
00114 { return _boundary_transform_determinants(integrator_node); }
00115
00117 const ublas::fixed_vector<float_t, fem_types::data_dimension> & boundary_normal() const
00118 { return _boundary_normal; }
00119
00121 std::size_t current_element() const { return _current_element; }
00122
00124 std::size_t current_boundary_element() const { return _current_boundary_element; }
00125
00127 bool is_boundary_node(std::size_t element_node) const { return _grid.is_boundary_node(_current_element,element_node); }
00128
00130 const ublas::fixed_vector<float_t, fem_types::data_dimension> boundary_normal_at_node(std::size_t element_node) const { return _grid.boundary_normal(_current_element, element_node); }
00131 }
00132 ;
00133
00134 template <class fem_types>
00135 void FemKernel<fem_types>::set_element(std::size_t element)
00136 {
00137 transform_t transform;
00138 shape_function_t shape_function;
00139 integrator_t integrator;
00140
00141 _current_element = element;
00142
00143 _grid.element_transform(element, transform);
00144
00145 for(std::size_t integrator_node = 0; integrator_node < integrator_t::n_nodes; ++integrator_node)
00146 {
00147 ublas::fixed_matrix<float_t, data_dimension, data_dimension> derivative, inverse_derivative;
00148 ublas::fixed_vector<float_t, data_dimension> temp;
00149
00150 transform.derivative(integrator.node(integrator_node), derivative);
00151 inverse_derivative = inverse(derivative);
00152
00153 _transform_determinants(integrator_node) = transform_det(derivative);
00154
00155 for(std::size_t element_node = 0; element_node < n_element_nodes; ++element_node)
00156 {
00157 _shape_values(integrator_node)(element_node) = shape_function.value(element_node, integrator.node(integrator_node));
00158 shape_function.gradient(element_node, integrator.node(integrator_node), temp);
00159 _shape_gradients(integrator_node)(element_node) = prod(temp, inverse_derivative);
00160 }
00161 }
00162
00163 }
00164
00165
00166
00167 template <class fem_types>
00168 void FemKernel<fem_types>::set_boundary_element(std::size_t element)
00169 {
00170 transform_t transform;
00171 shape_function_t shape_function;
00172 boundary_integrator_t integrator;
00173 std::size_t parent_element = _grid.parent_element(element);
00174 std::size_t parent_element_face = _grid.parent_element_face(element);
00175
00176 _current_boundary_element = element;
00177
00178 _grid.element_transform(parent_element, transform);
00179
00180 transform.boundary_normal(parent_element_face, _boundary_normal);
00181
00182 for(std::size_t integrator_node = 0; integrator_node < boundary_integrator_t::n_nodes; ++integrator_node)
00183 {
00184 ublas::fixed_matrix<float_t, data_dimension, data_dimension> derivative, inverse_derivative;
00185 ublas::fixed_matrix<float_t, data_dimension, data_dimension - 1> boundary_transform_derivative;
00186 ublas::fixed_vector<float_t, data_dimension> element_coordinates, gradient, boundary_normal, transformed_boundary_normal, temp;
00187
00188 transform.boundary2element(parent_element_face, integrator.node(integrator_node), element_coordinates);
00189
00190 transform.derivative(element_coordinates, derivative);
00191 inverse_derivative = inverse(derivative);
00192 transform.boundary_derivative(parent_element_face, integrator.node(integrator_node), boundary_transform_derivative);
00193
00194 _boundary_transform_determinants(integrator_node) = transform_det(boundary_transform_derivative);
00195
00196 for(std::size_t element_node = 0; element_node < n_element_nodes; ++element_node)
00197 {
00198 _shape_boundary_values(integrator_node)(element_node) =
00199 shape_function.value(element_node, element_coordinates);
00200
00201 shape_function.gradient(element_node, element_coordinates, temp);
00202 gradient = prod(temp, inverse_derivative);
00203
00204 _shape_boundary_derivatives(integrator_node)(element_node) = inner_prod(gradient, transformed_boundary_normal);
00205 }
00206 }
00207 }
00208
00209 template <>
00210 float_t transform_det(const ublas::fixed_matrix<float_t, 1, 0> & derivative);
00211
00212 template <>
00213 float_t transform_det(const ublas::fixed_matrix<float_t, 1, 1> & derivative);
00214
00215 template <>
00216 float_t transform_det(const ublas::fixed_matrix<float_t, 2, 1> & derivative);
00217
00218 template <>
00219 float_t transform_det(const ublas::fixed_matrix<float_t, 3, 2> & derivative);
00220
00221 }
00222
00223
00224 #endif