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