void FVMesh3D::complete_data() { // initialize the list of cell for each vertex for(size_t i=0;i<_nb_vertex;i++) { _vertex[i].nb_cell=0; } // we have to determine the list of neighbor cell for each vertex further // compute the centroid and length of edge for(size_t i=0;i<_nb_edge;i++) { _edge[i].centroid=(_edge[i].firstVertex->coord+_edge[i].secondVertex->coord)*(double)0.5; FVPoint3D<double> u; u=_edge[i].firstVertex->coord-_edge[i].secondVertex->coord; _edge[i].length=Norm(u); } // We have completly finish with the edge // compute geometric stuff for the face for(size_t i=0;i<_nb_face;i++) { _face[i].perimeter=0.; _face[i].area=0.; _face[i].centroid=0.; // conpute perimeter or the face for(size_t j=0;j<_face[i].nb_edge;j++) { _face[i].perimeter+=_face[i].edge[j]->length; _face[i].centroid+=_face[i].edge[j]->centroid*_face[i].edge[j]->length; } // compute the centroid of the face _face[i].centroid/=_face[i].perimeter; // compute the area of the face for(size_t j=0;j<_face[i].nb_edge;j++) { FVPoint3D<double> u,v,w; u=_face[i].edge[j]->firstVertex->coord-_face[i].centroid; v=_face[i].edge[j]->secondVertex->coord-_face[i].centroid; w=CrossProduct(u,v); _face[i].area+=Norm(w)*0.5; } // build the list of vertex pointer for the face pos_v=0; for(size_t j=0;j<_face[i].nb_edge;j++) { bool _still_exist; _still_exist=false; for(size_t k=0;k<pos_v;k++) if(_face[i].edge[j]->firstVertex==_face[i].vertex[k]) _still_exist=true; if(!_still_exist) {_face[i].vertex[pos_v]=_face[i].edge[j]->firstVertex;pos_v++;} _still_exist=false; for(size_t k=0;k<pos_v;k++) if(_face[i].edge[j]->secondVertex==_face[i].vertex[k]) _still_exist=true; if(!_still_exist) {_face[i].vertex[pos_v]=_face[i].edge[j]->secondVertex;pos_v++;} } _face[i].nb_vertex=pos_v; } // left and right cell, normal vector will be determined after the loop on cells // end loop on the faces for(size_t i=0;i<_nb_cell;i++) { _cell[i].surface=0.; _cell[i].volume=0.; _cell[i].centroid=0.; // conpute surface of the cell // determine the left and right cell for the face for(size_t j=0;j<_cell[i].nb_face;j++) { size_t pos; _cell[i].surface+=_cell[i].face[j]->area; _cell[i].centroid+=_cell[i].face[j]->centroid*_cell[i].face[j]->area; pos=_cell[i].face[j]->label-1; if(!(_face[pos].leftCell) ) _face[pos].leftCell=&(_cell[i]); else _face[pos].rightCell=&(_cell[i]); } // compute the centroid of the cell _cell[i].centroid/=_cell[i].surface; // compute the cell2face vector // compute the volume of the cell for(size_t j=0;j<_cell[i].nb_face;j++) { _cell[i].cell2face[j]= _cell[i].face[j]->centroid-_cell[i].centroid; for(size_t k=0;k<_cell[i].face[j]->nb_edge;k++) { FVPoint3D<double> u,v,w; u=_cell[i].cell2face[j]; v=_cell[i].face[j]->edge[k]->firstVertex->coord-_cell[i].centroid; w=_cell[i].face[j]->edge[k]->secondVertex->coord-_cell[i].centroid; _cell[i].volume+=fabs(Det(u,v,w))/6; } } // build the list of the vertex pointer for a cell pos_v=0; for(size_t j=0;j<_cell[i].nb_face;j++) for(size_t k=0;k<_cell[i].face[j]->nb_edge;k++) { bool _still_exist; _still_exist=false; for(size_t m=0;m<pos_v;m++) if(_cell[i].face[j]->edge[k]->firstVertex==_cell[i].vertex[m]) _still_exist=true; if(!_still_exist) {_cell[i].vertex[pos_v]=_cell[i].face[j]->edge[k]->firstVertex;pos_v++;} _still_exist=false; for(size_t m=0;m<pos_v;m++) if(_cell[i].face[j]->edge[k]->secondVertex==_cell[i].vertex[m]) _still_exist=true; if(!_still_exist) {_cell[i].vertex[pos_v]=_cell[i].face[j]->edge[k]->secondVertex;pos_v++;} } _cell[i].nb_vertex=pos_v; // build the list of the cell pointer for a vertex for(size_t j=0;j<_cell[i].nb_vertex;j++) { size_t pos; pos=_cell[i].vertex[j]->label-1; _vertex[pos].cell[_vertex[pos].nb_cell]=&(_cell[i]); _vertex[pos].nb_cell++; if(_vertex[pos].nb_cell>=NB_CELL_PER_VERTEX_3D) cout<<"Warning, overflow in class FVVertex3D, too many Cells, found "<<_vertex[pos].nb_cell<<endl; } } // we compute the normal from left to rigth for each sub-triangle _boundary_face.resize(0); _nb_boundary_face=0; for(size_t i=0;i<_nb_face;i++) { for(size_t j=0;j<_face[i].nb_edge;j++) { FVPoint3D<double> u,v,w; double no; u=_face[i].edge[j]->firstVertex->coord-_face[i].centroid; v=_face[i].edge[j]->secondVertex->coord-_face[i].centroid; w=CrossProduct(u,v); no=Norm(w); w/=no; _face[i].normal[j]=w; u=_face[i].centroid-_face[i].leftCell->centroid; if(w*u<0) _face[i].normal[j]*=-1.; } // build the list of boundary face if(! (_face[i].rightCell)) {_boundary_face.push_back(&(_face[i]));_nb_boundary_face++;} } }
bool AdFront2 :: SameSide (const Point<2> & lp1, const Point<2> & lp2, const Array<int> * testfaces) const { int cnt = 0; if (testfaces) { for (int ii = 0; ii < testfaces->Size(); ii++) if (lines[(*testfaces)[ii]].Valid()) { int i = (*testfaces)[ii]; const Point<3> & p13d = points[lines[i].L().I1()].P(); const Point<3> & p23d = points[lines[i].L().I2()].P(); Point<2> p1(p13d(0), p13d(1)); Point<2> p2(p23d(0), p23d(1)); // p1 + alpha v = lp1 + beta vl Vec<2> v = p2-p1; Vec<2> vl = lp2 - lp1; Mat<2,2> mat, inv; Vec<2> rhs, sol; mat(0,0) = v(0); mat(1,0) = v(1); mat(0,1) = -vl(0); mat(1,1) = -vl(1); rhs = lp1-p1; if (Det(mat) == 0) continue; CalcInverse (mat, inv); sol = inv * rhs; if (sol(0) >= 0 && sol(0) <= 1 & sol(1) >= 0 && sol(1) <= 1) { cnt++; } } } else { for (int i = 0; i < lines.Size(); i++) if (lines[i].Valid()) { const Point<3> & p13d = points[lines[i].L().I1()].P(); const Point<3> & p23d = points[lines[i].L().I2()].P(); Point<2> p1(p13d(0), p13d(1)); Point<2> p2(p23d(0), p23d(1)); // p1 + alpha v = lp1 + beta vl Vec<2> v = p2-p1; Vec<2> vl = lp2 - lp1; Mat<2,2> mat, inv; Vec<2> rhs, sol; mat(0,0) = v(0); mat(1,0) = v(1); mat(0,1) = -vl(0); mat(1,1) = -vl(1); rhs = lp1-p1; if (Det(mat) == 0) continue; CalcInverse (mat, inv); sol = inv * rhs; if (sol(0) >= 0 && sol(0) <= 1 & sol(1) >= 0 && sol(1) <= 1) { cnt++; } } } return ((cnt % 2) == 0); }
// |M| float Det(const Matrix3& m) { return Det(m.mat); }
void Matrix44f::invert( void ) { float fDet = _11*Det( _22, _23, _24, _32, _33, _34, _42, _43, _44 ) - _12*Det( _21, _23, _24, _31, _33, _34, _41, _43, _44 ) + _13*Det( _21, _22, _24, _31, _32, _34, _41, _42, _44 ) - _14*Det( _21, _22, _23, _31, _32, _33, _41, _42, _43 ); // determinant must be not zero if( fabsf( fDet ) < 0.00001f ) // error determinant is zero return; fDet = 1.0f / fDet; Matrix44f mMatrix; // Row1 mMatrix._11 = Det( _22, _23, _24, _32, _33, _34, _42, _43, _44 ); mMatrix._12 = -1.0f * Det( _21, _23, _24, _31, _33, _34, _41, _43, _44 ); mMatrix._13 = Det( _21, _22, _24, _31, _32, _34, _41, _42, _44 ); mMatrix._14 = -1.0f * Det( _21, _22, _23, _31, _32, _33, _41, _42, _43 ); // Row2 mMatrix._21 = -1.0f * Det( _12, _13, _14, _32, _33, _34, _42, _43, _44 ); mMatrix._22 = Det( _11, _13, _14, _31, _33, _34, _41, _43, _44 ); mMatrix._23 = -1.0f * Det( _11, _12, _14, _31, _32, _34, _41, _42, _44 ); mMatrix._24 = Det( _11, _12, _13, _31, _32, _33, _41, _42, _43 ); // Row3 mMatrix._31 = Det( _12, _13, _14, _22, _23, _24, _42, _43, _44 ); mMatrix._32 = -1.0f * Det( _11, _13, _14, _21, _23, _24, _41, _43, _44 ); mMatrix._33 = Det( _11, _12, _14, _21, _22, _24, _41, _42, _44 ); mMatrix._34 = -1.0f * Det( _11, _12, _13, _21, _22, _23, _41, _42, _43 ); // Row4 mMatrix._41 = -1.0f * Det( _12, _13, _14, _22, _23, _24, _32, _33, _34 ); mMatrix._42 = Det( _11, _13, _14, _21, _23, _24, _31, _33, _34 ); mMatrix._43 = -1.0f * Det( _11, _12, _14, _21, _22, _24, _31, _32, _34 ); mMatrix._44 = Det( _11, _12, _13, _21, _22, _23, _31, _32, _33 ); _11 = fDet*mMatrix._11; _12 = fDet*mMatrix._21; _13 = fDet*mMatrix._31; _14 = fDet*mMatrix._41; _21 = fDet*mMatrix._12; _22 = fDet*mMatrix._22; _23 = fDet*mMatrix._32; _24 = fDet*mMatrix._42; _31 = fDet*mMatrix._13; _32 = fDet*mMatrix._23; _33 = fDet*mMatrix._33; _34 = fDet*mMatrix._43; _41 = fDet*mMatrix._14; _42 = fDet*mMatrix._24; _43 = fDet*mMatrix._34; _44 = fDet*mMatrix._44; }
void TestBandDiv(tmv::DivType dt) { const int N = 10; std::vector<tmv::BandMatrixView<T> > b; std::vector<tmv::BandMatrixView<std::complex<T> > > cb; MakeBandList(b,cb); tmv::Matrix<T> a1(N,N); for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) a1(i,j) = T(3+i-2*j); a1.diag().addToAll(T(10)*N); a1 /= T(10); tmv::Matrix<std::complex<T> > ca1 = a1 * std::complex<T>(3,-4); tmv::Vector<T> v1(N); tmv::Vector<T> v2(N-1); for (int i=0; i<N; ++i) v1(i) = T(16-3*i); for (int i=0; i<N-1; ++i) v2(i) = T(-6+i); tmv::Vector<std::complex<T> > cv1(N); tmv::Vector<std::complex<T> > cv2(N-1); for (int i=0; i<N; ++i) cv1(i) = std::complex<T>(16-3*i,i+4); for (int i=0; i<N-1; ++i) cv2(i) = std::complex<T>(2*i-3,-6+i); tmv::Matrix<T> a3 = a1.colRange(0,N/2); tmv::Matrix<std::complex<T> > ca3 = ca1.colRange(0,N/2); tmv::Matrix<T> a4 = a1.rowRange(0,N/2); tmv::Matrix<std::complex<T> > ca4 = ca1.rowRange(0,N/2); tmv::Matrix<T> a5 = a1.colRange(0,0); tmv::Matrix<std::complex<T> > ca5 = ca1.colRange(0,0); tmv::Matrix<T> a6 = a1.rowRange(0,0); tmv::Matrix<std::complex<T> > ca6 = ca1.rowRange(0,0); tmv::Matrix<T> a7 = a1; tmv::Matrix<std::complex<T> > ca7 = ca1; a7.diag().addToAll(T(10)*N); ca7.diag().addToAll(T(10)*N); for(size_t i=START;i<b.size();i++) { if (showstartdone) std::cout<<"Start loop: i = "<<i<<"\nbi = "<<tmv::TMV_Text(b[i])<< " "<<b[i]<<std::endl; tmv::BandMatrixView<T> bi = b[i]; tmv::BandMatrixView<std::complex<T> > cbi = cb[i]; if (dt == tmv::LU && !bi.isSquare()) continue; bi.saveDiv(); cbi.saveDiv(); tmv::Matrix<T> m(bi); m.saveDiv(); bi.divideUsing(dt); bi.setDiv(); m.divideUsing(dt); m.setDiv(); std::ostream* divout = showdiv ? &std::cout : 0; Assert(bi.checkDecomp(divout),"CheckDecomp"); T eps = m.rowsize()*EPS*Norm(m)*Norm(m.inverse()); if (bi.colsize() == N) { tmv::Vector<T> x1 = v1/bi; tmv::Vector<T> x2 = v1/m; if (showacc) { std::cout<<"v/b: Norm(x1-x2) = "<<Norm(x1-x2)<< " "<<eps*Norm(x1)<<std::endl; } Assert(Norm(x1-x2) < eps*Norm(x1),"Band v/b"); } if (bi.rowsize() == N) { tmv::Vector<T> x1 = v1%bi; tmv::Vector<T> x2 = v1%m; if (showacc) { std::cout<<"v%b: Norm(x1-x2) = "<<Norm(x1-x2)<< " "<<eps*Norm(x1)<<std::endl; } Assert(Norm(x1-x2) < eps*Norm(x1),"Band v%b"); } tmv::Matrix<T,tmv::ColMajor> binv = bi.inverse(); tmv::Matrix<T,tmv::ColMajor> minv = m.inverse(); if (showacc) { std::cout<<"minv = "<<minv<<std::endl; std::cout<<"binv = "<<binv<<std::endl; std::cout<<"Norm(minv-binv) = "<<Norm(minv-binv)<< " "<<eps*Norm(binv)<<std::endl; } Assert(Norm(binv-minv) < eps*Norm(binv),"Band Inverse"); if (m.isSquare()) { if (showacc) { std::cout<<"Det(b) = "<<Det(bi)<< ", Det(m) = "<<Det(m)<<std::endl; std::cout<<"abs(bdet-mdet) = "<<std::abs(Det(bi)-Det(m)); std::cout<<" EPS*abs(mdet) = "<< eps*std::abs(Det(m))<<std::endl; std::cout<<"abs(abs(bdet)-abs(mdet)) = "<< std::abs(std::abs(Det(bi))-std::abs(Det(m))); std::cout<<" EPS*abs(mdet) = "<< eps*std::abs(Det(m))<<std::endl; } Assert(std::abs(Det(m)-Det(bi)) < eps*std::abs(Det(m)+Norm(m)), "Band Det"); T msign, bsign; Assert(std::abs(m.logDet(&msign)-bi.logDet(&bsign)) < N*eps, "Band LogDet"); Assert(std::abs(msign-bsign) < N*eps,"Band LogDet - sign"); } cbi.divideUsing(dt); cbi.setDiv(); Assert(cbi.checkDecomp(divout),"CheckDecomp"); tmv::Matrix<std::complex<T> > cm(cbi); cm.saveDiv(); cm.divideUsing(dt); cm.setDiv(); T ceps = EPS*Norm(cm)*Norm(cm.inverse()); if (cm.isSquare()) { if (showacc) { std::cout<<"Det(cbi) = "<<Det(cbi)<<", Det(cm) = "<< Det(cm)<<std::endl; std::cout<<"abs(cbidet-cmdet) = "<<std::abs(Det(cbi)-Det(cm)); std::cout<<" cbidet/cmdet = "<<Det(cbi)/Det(cm); std::cout<<" EPS*abs(cmdet) = "<< ceps*std::abs(Det(cm))<<std::endl; std::cout<<"abs(abs(bdet)-abs(mdet)) = "<< std::abs(std::abs(Det(bi))-std::abs(Det(m))); std::cout<<" EPS*abs(mdet) = "<< ceps*std::abs(Det(m))<<std::endl; } Assert(std::abs(Det(cbi)-Det(cm)) < ceps*std::abs(Det(cm)+Norm(cm)), "Band CDet"); std::complex<T> cmsign, cbsign; Assert(std::abs(cm.logDet(&cmsign)-cbi.logDet(&cbsign)) < N*eps, "Band CLogDet"); Assert(std::abs(cmsign-cbsign) < N*eps,"Band CLogDet - sign"); } tmv::Vector<std::complex<T> > cv(v1 * std::complex<T>(1,1)); cv(1) += std::complex<T>(-1,5); cv(2) -= std::complex<T>(-1,5); if (m.colsize() == N) { // test real / complex tmv::Vector<std::complex<T> > y1 = v1/cbi; tmv::Vector<std::complex<T> > y2 = v1/cm; if (showacc) { std::cout<<"v/cb: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<ceps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < ceps*Norm(y1),"Band v/cb"); // test complex / real y1 = cv/bi; y2 = cv/m; if (showacc) { std::cout<<"cv/b: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<eps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < eps*Norm(y1),"Band cv/b"); // test complex / complex y1 = cv/cbi; y2 = cv/cm; if (showacc) { std::cout<<"cv/cb: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<ceps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < ceps*Norm(y1),"Band cv/cb"); } if (bi.rowsize() == N) { tmv::Vector<std::complex<T> > y1 = v1%cbi; tmv::Vector<std::complex<T> > y2 = v1%cm; if (showacc) { std::cout<<"v%cb: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<ceps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < ceps*Norm(y1),"Band v%cb"); y1 = cv%bi; y2 = cv%m; if (showacc) { std::cout<<"cv%b: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<eps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < eps*Norm(y1),"Band cv%b"); y1 = cv%cbi; y2 = cv%cm; if (showacc) { std::cout<<"cv%cb: Norm(y1-y2) = "<<Norm(y1-y2)<< " "<<ceps*Norm(y1)<<std::endl; } Assert(Norm(y1-y2) < ceps*Norm(y1),"Band cv%cb"); } } TestBandDiv_A<T>(dt); TestBandDiv_B1<T>(dt); TestBandDiv_B2<T>(dt); TestBandDiv_C1<T>(dt); if (dt == tmv::LU) TestBandDiv_C2<T>(dt); TestBandDiv_D1<T>(dt); if (dt == tmv::LU) TestBandDiv_D2<T>(dt); std::cout<<"BandMatrix<"<<tmv::TMV_Text(T())<<"> Division using "; std::cout<<tmv::TMV_Text(dt)<<" passed all tests\n"; }
bool link_det_minor( size_t size , size_t repeat , CppAD::vector<double> &matrix , CppAD::vector<double> &gradient ) { // ----------------------------------------------------- // setup // object for computing determinant typedef CppAD::AD<double> ADScalar; typedef CppAD::vector<ADScalar> ADVector; CppAD::det_by_minor<ADScalar> Det(size); size_t i; // temporary index size_t m = 1; // number of dependent variables size_t n = size * size; // number of independent variables ADVector A(n); // AD domain space vector ADVector detA(m); // AD range space vector // vectors of reverse mode weights CppAD::vector<double> w(1); w[0] = 1.; // the AD function object CppAD::ADFun<double> f; static bool printed = false; bool print_this_time = (! printed) & (repeat > 1) & (size >= 3); extern bool global_retape; if( global_retape ) while(repeat--) { // choose a matrix CppAD::uniform_01(n, matrix); for( i = 0; i < size * size; i++) A[i] = matrix[i]; // declare independent variables Independent(A); // AD computation of the determinant detA[0] = Det(A); // create function object f : A -> detA f.Dependent(A, detA); extern bool global_optimize; if( global_optimize ) { size_t before, after; before = f.size_var(); f.optimize(); if( print_this_time ) { after = f.size_var(); std::cout << "cppad_det_minor_optimize_size_" << int(size) << " = [ " << int(before) << ", " << int(after) << "]" << std::endl; printed = true; print_this_time = false; } } // get the next matrix CppAD::uniform_01(n, matrix); // evaluate the determinant at the new matrix value f.Forward(0, matrix); // evaluate and return gradient using reverse mode gradient = f.Reverse(1, w); } else { // choose a matrix CppAD::uniform_01(n, matrix); for( i = 0; i < size * size; i++) A[i] = matrix[i]; // declare independent variables Independent(A); // AD computation of the determinant detA[0] = Det(A); // create function object f : A -> detA CppAD::ADFun<double> f; f.Dependent(A, detA); extern bool global_optimize; if( global_optimize ) { size_t before, after; before = f.size_var(); f.optimize(); if( print_this_time ) { after = f.size_var(); std::cout << "optimize: size = " << size << ": size_var() = " << before << "(before) " << after << "(after) " << std::endl; printed = true; print_this_time = false; } } // ------------------------------------------------------ while(repeat--) { // get the next matrix CppAD::uniform_01(n, matrix); // evaluate the determinant at the new matrix value f.Forward(0, matrix); // evaluate and return gradient using reverse mode gradient = f.Reverse(1, w); } } return true; }
bool link_det_minor( size_t size , size_t repeat , CppAD::vector<double> &matrix , CppAD::vector<double> &gradient ) { // speed test global option values if( global_option["atomic"] ) return false; // ----------------------------------------------------- // setup // object for computing determinant typedef CppAD::AD<double> ADScalar; typedef CppAD::vector<ADScalar> ADVector; CppAD::det_by_minor<ADScalar> Det(size); size_t i; // temporary index size_t m = 1; // number of dependent variables size_t n = size * size; // number of independent variables ADVector A(n); // AD domain space vector ADVector detA(m); // AD range space vector // vectors of reverse mode weights CppAD::vector<double> w(1); w[0] = 1.; // the AD function object CppAD::ADFun<double> f; // --------------------------------------------------------------------- if( ! global_option["onetape"] ) while(repeat--) { // choose a matrix CppAD::uniform_01(n, matrix); for( i = 0; i < size * size; i++) A[i] = matrix[i]; // declare independent variables Independent(A); // AD computation of the determinant detA[0] = Det(A); // create function object f : A -> detA f.Dependent(A, detA); if( global_option["optimize"] ) f.optimize(); // skip comparison operators f.compare_change_count(0); // evaluate the determinant at the new matrix value f.Forward(0, matrix); // evaluate and return gradient using reverse mode gradient = f.Reverse(1, w); } else { // choose a matrix CppAD::uniform_01(n, matrix); for( i = 0; i < size * size; i++) A[i] = matrix[i]; // declare independent variables Independent(A); // AD computation of the determinant detA[0] = Det(A); // create function object f : A -> detA f.Dependent(A, detA); if( global_option["optimize"] ) f.optimize(); // skip comparison operators f.compare_change_count(0); // ------------------------------------------------------ while(repeat--) { // get the next matrix CppAD::uniform_01(n, matrix); // evaluate the determinant at the new matrix value f.Forward(0, matrix); // evaluate and return gradient using reverse mode gradient = f.Reverse(1, w); } } return true; }