Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_SOLVERS_MBD_PROJECTED_GAUSS_SEIDEL_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_SOLVERS_MBD_PROJECTED_GAUSS_SEIDEL_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_ncp_solver_interface.h>
00013 #include <OpenTissue/dynamics/mbd/solvers/mbd_merit.h>
00014 #include <OpenTissue/core/math/math_is_number.h>
00015
00016 namespace OpenTissue
00017 {
00018 namespace mbd
00019 {
00020
00021 template< typename math_policy >
00022 class ProjectedGaussSeidel
00023 : public NCPSolverInterface<math_policy>
00024 {
00025 protected:
00026
00027 typedef typename math_policy::value_traits value_traits;
00028 typedef typename math_policy::real_type real_type;
00029 typedef typename math_policy::size_type size_type;
00030 typedef typename math_policy::matrix_type matrix_type;
00031 typedef typename math_policy::system_matrix_type system_matrix_type;
00032 typedef typename math_policy::vector_type vector_type;
00033 typedef typename math_policy::idx_vector_type idx_vector_type;
00034
00035 protected:
00036
00037 size_type m_iterations;
00038 bool m_profiling;
00039 vector_type m_theta;
00040 system_matrix_type m_A;
00041
00042 public:
00043
00044 void set_max_iterations(size_type value)
00045 {
00046 assert(value>0 || !"ProjectedGaussSeidel::set_max_iterations(): value must be positive");
00047 m_iterations = value;
00048 }
00049
00050 bool & profiling() { return m_profiling; }
00051 bool const & profiling() const { return m_profiling; }
00052
00053 vector_type const & theta() const { return m_theta; }
00054
00055
00056 real_type get_accuracy() const { return value_traits::zero(); }
00057 size_t get_iteration() const { return 0; }
00058
00059
00060 public:
00061
00062 ProjectedGaussSeidel()
00063 : m_iterations(5)
00064 , m_profiling(false)
00065 {}
00066
00067 virtual ~ProjectedGaussSeidel(){}
00068
00069 public:
00070
00071 void run(
00072 matrix_type const & J
00073 , matrix_type const & W
00074 , vector_type const & gamma
00075 , vector_type const & b
00076 , vector_type & lo
00077 , vector_type & hi
00078 , idx_vector_type const & pi
00079 , vector_type const & mu
00080 , vector_type & x
00081 )
00082 {
00083 using std::fabs;
00084
00085 if(this->profiling())
00086 math_policy::resize(m_theta,m_iterations);
00087
00088 size_type m;
00089 math_policy::get_dimension(b,m);
00090
00091 if(m==0)
00092 return;
00093
00094 math_policy::compute_system_matrix(W, J, m_A);
00095
00096 math_policy::init_system_matrix(m_A,x);
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 for (size_type k = 0; k < m_iterations; ++k)
00125 {
00126 for (size_type i = 0; i < m; ++ i)
00127 {
00128 real_type new_x = - b(i);
00129 new_x -= math_policy::row_prod(m_A,i,x);
00130
00131 assert(is_number(gamma(i)) || !"ProjectedGaussSeidel::run(): not a number encountered");
00132 assert(gamma(i)>= value_traits::zero() || !"ProjectedGaussSeidel::run(): gamma(i) was less than 0");
00133
00134 if(gamma(i) > value_traits::zero())
00135 {
00136
00137 real_type alpha = value_traits::one()*(m_iterations-1-k)/(m_iterations-1);
00138
00139 assert(is_number(alpha) || !"ProjectedGaussSeidel::run(): not a number encountered");
00140 assert(alpha<= value_traits::one() || !"ProjectedGaussSeidel::run(): alpha was greater than 1");
00141 assert(alpha>= value_traits::zero() || !"ProjectedGaussSeidel::run(): alpha was less than 0");
00142
00143 new_x -= gamma(i)*alpha*x(i);
00144 new_x /= m_A(i,i) + gamma(i)*alpha;
00145 }
00146 else
00147 {
00148 assert(m_A(i,i)>0 || m_A(i,i)<0 || !"ProjectedGaussSeidel::run(): diagonal entry is zero?");
00149 new_x /= m_A(i,i);
00150 }
00151
00152 new_x += x(i);
00153
00154 assert(is_number(new_x) || !"ProjectedGaussSeidel::run(): not a number encountered");
00155
00156 size_type j = pi(i);
00157 if (j < m )
00158 {
00159 assert(is_number(mu(i)) || !"ProjectedGaussSeidel::run(): not a number encountered");
00160 hi(i) = fabs(mu(i)*x(j));
00161 lo(i) = - hi(i);
00162 }
00163
00164 assert(lo(i)<= value_traits::zero() || !"ProjectedGaussSeidel::run(): lower limit was positive");
00165 assert(hi(i)>= value_traits::zero() || !"ProjectedGaussSeidel::run(): upper limit was negative");
00166
00167 real_type old_x = x(i);
00168 if(new_x < lo(i))
00169 x(i) = lo(i);
00170 else if(new_x > hi(i))
00171 x(i) = hi(i);
00172 else
00173 x(i) = new_x;
00174
00175 real_type dx = x(i)-old_x;
00176
00177 math_policy::update_system_matrix(m_A,i,dx);
00178
00179 assert(is_number(x(i)) || !"ProjectedGaussSeidel::run(): not a number encountered");
00180 }
00181
00182 if(this->profiling())
00183 m_theta(k) = mbd::merit(m_A,x,b,lo,hi,math_policy());
00184 }
00185 }
00186
00187 };
00188
00189 }
00190 }
00191
00192
00193 #endif