00001 #ifndef EQUATION_MCMSTEP_H
00002 #define EQUATION_MCMSTEP_H
00003
00004 #include <fem/equation/SimpleEquationInterface.hpp>
00005 #include <boost/shared_ptr.hpp>
00006
00007 namespace imaging
00008 {
00018 template<class fem_types>
00019 class McmStep : public SimpleEquationInterface<fem_types>
00020 {
00021 boost::shared_ptr< ublas::vector<float_t> > _input_ptr;
00022 float_t _epsilon;
00023 float_t _step_size;
00024
00025 float_t regularized_abs(const ublas::fixed_vector<float_t, fem_types::data_dimension > & vector) const
00026 {
00027 return sqrt(square(_epsilon) + inner_prod(vector, vector));
00028 }
00029
00030 public:
00031 typedef ublas::fixed_matrix<float_t, fem_types::data_dimension, fem_types::data_dimension> matrix_coefficient_t;
00032 typedef typename ublas::fixed_vector<float_t, fem_types::data_dimension> vector_coefficient_t;
00033
00034 McmStep() : _step_size(0.0), _epsilon(1.0) {}
00035
00037 const ublas::vector<float_t> & input() const { return *_input_ptr; }
00038
00040 void set_input(boost::shared_ptr< ublas::vector<float_t> > input_ptr) { _input_ptr = input_ptr; }
00041
00043 float_t step_size() const { return _step_size; }
00044
00046 void set_step_size(float_t step_size) { _step_size = step_size; }
00047
00049 float_t epsilon() const {return _epsilon; }
00050
00052 void set_epsilon(float_t epsilon) { _epsilon = epsilon; }
00053
00054 static const bool a_active = false;
00055 static const bool b_active = false;
00056 static const bool c_active = true;
00057 static const bool f_active = true;
00058 static const bool g_active = false;
00059
00060 static const size_t boundary_data_type = SimpleEquationInterface<fem_types>::NO_BOUNDARY_DATA;
00061
00062 void stiffness_matrix(std::size_t integrator_node,
00063 const FemKernel<fem_types> & kernel,
00064 matrix_coefficient_t & A,
00065 ublas::fixed_vector<float_t, fem_types::data_dimension> & a,
00066 ublas::fixed_vector<float_t, fem_types::data_dimension> & b,
00067 float_t & c) const
00068 {
00069 ublas::fixed_vector <float_t, fem_types::data_dimension> local_gradient;
00070 kernel.grid().interpolate_gradient(integrator_node, *_input_ptr, kernel, local_gradient);
00071
00072 float_t regularized_abs_gradient = regularized_abs(local_gradient);
00073 A = _step_size / regularized_abs_gradient * ublas::identity_matrix<float_t>(fem_types::data_dimension);
00074 c = 1.0 / regularized_abs_gradient;
00075 }
00076
00077 void force_vector(std::size_t integrator_node,
00078 const FemKernel<fem_types> & kernel,
00079 float_t & f,
00080 ublas::fixed_vector<float_t, fem_types::data_dimension> & g) const
00081 {
00082 float_t local_input;
00083 kernel.grid().interpolate_value(integrator_node, *_input_ptr, kernel, local_input);
00084
00085 ublas::fixed_vector <float_t, fem_types::data_dimension> local_gradient;
00086 kernel.grid().interpolate_gradient(integrator_node, *_input_ptr, kernel, local_gradient);
00087
00088 f = local_input / regularized_abs(local_gradient);
00089 }
00090
00091 bool sanity_check_stiffness_matrix(const FemKernel<fem_types> & kernel, std::string & error_message) const
00092 {
00093 if(! _input_ptr)
00094 return false;
00095
00096 if(_input_ptr->size() != kernel.grid().n_nodes())
00097 return false;
00098
00099 return true;
00100 }
00101
00102 bool sanity_check_force_vector(const FemKernel<fem_types> & kernel, std::string & error_message) const
00103 {
00104 if(! _input_ptr)
00105 return false;
00106
00107 if(_input_ptr->size() != kernel.grid().n_nodes())
00108 return false;
00109
00110 return true;
00111 }
00112
00113 };
00114
00115 }
00116
00117
00118 #endif