Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_FEM_FEM_CONJUGATE_GRADIENTS_H
00002 #define OPENTISSUE_DYNAMICS_FEM_FEM_CONJUGATE_GRADIENTS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 namespace OpenTissue
00013 {
00014 namespace fem
00015 {
00016 namespace detail
00017 {
00025 template < typename fem_mesh >
00026 inline void conjugate_gradients(
00027 fem_mesh & mesh
00028 , unsigned int min_iterations
00029 , unsigned int max_iterations
00030 )
00031 {
00032 using std::fabs;
00033
00034 typedef typename fem_mesh::real_type real_type;
00035 typedef typename fem_mesh::vector3_type vector3_type;
00036 typedef typename fem_mesh::matrix3x3_type matrix3x3_type;
00037 typedef typename fem_mesh::node_iterator node_iterator;
00038 typedef typename fem_mesh::node_type::matrix_iterator matrix_iterator;
00039
00040 node_iterator begin = mesh.node_begin();
00041 node_iterator end = mesh.node_end();
00042
00043 real_type tiny = 1e-010;
00044 real_type tolerence = 0.001;
00045
00046
00047
00048 for(node_iterator n_i=begin;n_i!=end;++n_i)
00049 {
00050 if(n_i->m_fixed)
00051 continue;
00052
00053 n_i->m_residual = n_i->m_b;
00054
00055 matrix_iterator Abegin = n_i->Abegin();
00056 matrix_iterator Aend = n_i->Aend();
00057 for (matrix_iterator A = Abegin; A != Aend;++A)
00058 {
00059 unsigned int j = A->first;
00060 matrix3x3_type & A_ij = A->second;
00061 node_iterator n_j = mesh.node(j);
00062 vector3_type & v_j = n_j->m_velocity;
00063
00064 n_i->m_residual -= A_ij * v_j;
00065 }
00066 n_i->m_prev = n_i->m_residual;
00067 }
00068
00069 for(unsigned int iteration = 0; iteration < max_iterations; ++iteration)
00070 {
00071 real_type d = 0.0;
00072 real_type d2 = 0.0;
00073
00074
00075
00076
00077
00078 for(node_iterator n_i=begin;n_i!=end;++n_i)
00079 {
00080 if(n_i->m_fixed)
00081 continue;
00082
00083 n_i->m_update.clear();
00084
00085 matrix_iterator Abegin = n_i->Abegin();
00086 matrix_iterator Aend = n_i->Aend();
00087 for (matrix_iterator A = Abegin; A != Aend;++A)
00088 {
00089
00090 unsigned int j = A->first;
00091 node_iterator n_j = mesh.node(j);
00092 matrix3x3_type & A_ij = A->second;
00093
00094 n_i->m_update += A_ij * n_j->m_prev;
00095
00096 }
00097 d += n_i->m_residual * n_i->m_residual;
00098 d2 += n_i->m_prev * n_i->m_update;
00099 }
00100
00101 if(fabs(d2) < tiny)
00102 d2 = tiny;
00103
00104 real_type d3 = d / d2;
00105 real_type d1 = 0.0;
00106
00107
00108
00109
00110 for(node_iterator n_i=begin;n_i!=end;++n_i)
00111 {
00112 if(n_i->m_fixed)
00113 continue;
00114 n_i->m_velocity += n_i->m_prev * d3;
00115 n_i->m_residual -= n_i->m_update * d3;
00116 d1 += n_i->m_residual * n_i->m_residual;
00117 }
00118 if(iteration >= min_iterations && d1 < tolerence)
00119 break;
00120
00121 if(fabs(d) < tiny)
00122 d = tiny;
00123
00124 real_type d4 = d1 / d;
00125
00126 for(node_iterator n_i=begin;n_i!=end;++n_i)
00127 {
00128 if(n_i->m_fixed)
00129 continue;
00130 n_i->m_prev = n_i->m_residual + n_i->m_prev * d4;
00131 }
00132 }
00133 }
00134
00135 }
00136 }
00137 }
00138
00139
00140 #endif