00001 #ifndef EQUATION_SIMPLEEQUATIONADAPTOR_H 00002 #define EQUATION_SIMPLEEQUATIONADAPTOR_H 00003 00004 00005 #include <fem/equation/EquationInterface.hpp> 00006 #include <fem/equation/SimpleEquationInterface.hpp> 00007 #include <fem/FemKernel.hpp> 00008 00009 00010 namespace imaging 00011 { 00034 template <class equation_t> 00035 class SimpleEquationAdaptor : public EquationInterface<typename equation_t::fem_types> 00036 { 00037 const equation_t & _equation; 00038 typedef typename equation_t::fem_types fem_types; 00039 00040 public: 00041 const std::size_t system_size() const { return 1; } 00042 00044 SimpleEquationAdaptor(const equation_t & equation) : _equation(equation) {} 00045 00046 float_t stiffness_matrix(std::size_t equation, std::size_t component, 00047 std::size_t i, std::size_t j, 00048 std::size_t integrator_node, 00049 const FemKernel<fem_types> & kernel) const 00050 { 00051 float_t value = 0.0; 00052 00053 typename equation_t::matrix_coefficient_t A; 00054 ublas::fixed_vector<float_t, fem_types::data_dimension> a, b; 00055 float_t c; 00056 00057 if( ! kernel.is_boundary_node(i) || 00058 _equation.boundary_data_type == SimpleEquationInterface<fem_types>::NO_BOUNDARY_DATA || 00059 _equation.boundary_data_type == SimpleEquationInterface<fem_types>::IMPLICIT_NEUMANN_DATA ) 00060 { 00061 _equation.stiffness_matrix(integrator_node, kernel, A, a, b, c); 00062 00063 value += inner_prod( prod(A, kernel.shape_gradient(integrator_node, i)), 00064 kernel.shape_gradient(integrator_node, j) ); 00065 00066 if(_equation.a_active) 00067 value += inner_prod(a, kernel.shape_gradient(integrator_node, j) ) * 00068 kernel.shape_value(integrator_node, i); 00069 00070 if(_equation.b_active) 00071 value += inner_prod(b, kernel.shape_gradient(integrator_node, i) ) * 00072 kernel.shape_value(integrator_node, j); 00073 00074 if(_equation.c_active) 00075 value += c * 00076 kernel.shape_value(integrator_node, i) * 00077 kernel.shape_value(integrator_node, j); 00078 } 00079 00080 return value; 00081 } 00082 00083 00084 float_t force_vector(std::size_t equation, 00085 std::size_t i, 00086 std::size_t integrator_node, 00087 const FemKernel<fem_types> & kernel) const 00088 { 00089 float_t value = 0.0; 00090 00091 float_t f; 00092 ublas::fixed_vector<float_t, fem_types::data_dimension> g; 00093 00094 if( ! kernel.is_boundary_node(i) || 00095 _equation.boundary_data_type == equation_t::NO_BOUNDARY_DATA || 00096 _equation.boundary_data_type == equation_t::IMPLICIT_NEUMANN_DATA ) 00097 { 00098 _equation.force_vector(integrator_node, kernel, f, g); 00099 00100 if(_equation.f_active) 00101 value += f * 00102 kernel.shape_value(integrator_node, i); 00103 00104 if(_equation.g_active) 00105 value += inner_prod(g, kernel.shape_gradient(integrator_node, i) ); 00106 } 00107 00108 return value; 00109 } 00110 00111 00112 float_t stiffness_matrix_at_boundary(std::size_t equation, std::size_t component, 00113 std::size_t i, std::size_t j, 00114 std::size_t integrator_node, 00115 const FemKernel<fem_types> & kernel) const 00116 { 00117 float_t value = 0.0; 00118 00119 float_t h; 00120 00121 if(_equation.boundary_data_type != equation_t::NO_BOUNDARY_DATA) 00122 { 00123 if(_equation.boundary_data_type == equation_t::MIXED_DATA) 00124 { 00125 _equation.stiffness_matrix_at_boundary(integrator_node, kernel, h); 00126 00127 value += kernel.shape_boundary_derivative(integrator_node, i) * kernel.shape_boundary_value(integrator_node, j) * 00128 kernel.boundary_transform_determinant(integrator_node); 00129 00130 value += h * 00131 kernel.shape_boundary_value(integrator_node, i) * kernel.shape_boundary_value(integrator_node, j); 00132 } 00133 00134 if(_equation.boundary_data_type == equation_t::NEUMANN_DATA) 00135 value += kernel.shape_boundary_derivative(integrator_node, i) * kernel.shape_boundary_value(integrator_node, j); 00136 00137 if(_equation.boundary_data_type == equation_t::DIRICHLET_DATA) 00138 value += kernel.shape_boundary_value(integrator_node, i) * kernel.shape_boundary_value(integrator_node, j); 00139 } 00140 00141 return value; 00142 } 00143 00144 00145 float_t force_vector_at_boundary(std::size_t equation, 00146 std::size_t i, 00147 std::size_t integrator_node, 00148 const FemKernel<fem_types> & kernel) const 00149 { 00150 float_t value = 0.0; 00151 00152 float_t v; 00153 00154 if(_equation.boundary_data_type != equation_t::NO_BOUNDARY_DATA) 00155 { 00156 _equation.force_vector_at_boundary(integrator_node, kernel, v); 00157 00158 if(_equation.boundary_data_type == equation_t::IMPLICIT_NEUMANN_DATA) 00159 value += -1.0 * 00160 v * 00161 kernel.shape_boundary_value(integrator_node, i); 00162 else 00163 value += v * 00164 kernel.shape_boundary_value(integrator_node, i); 00165 } 00166 00167 return value; 00168 } 00169 00170 bool sanity_check_stiffness_matrix(const FemKernel<fem_types> & kernel, std::string & error_message) const 00171 { 00172 return _equation.sanity_check_stiffness_matrix(kernel, error_message); 00173 } 00174 00175 bool sanity_check_force_vector(const FemKernel<fem_types> & kernel, std::string & error_message) const 00176 { 00177 return _equation.sanity_check_force_vector(kernel, error_message); 00178 } 00179 }; 00180 } 00181 00182 #endif 00183