getfem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Getfem-commits] r5396 - in /trunk/getfem/src: ./ getfem/ gmm/


From: Yves . Renard
Subject: [Getfem-commits] r5396 - in /trunk/getfem/src: ./ getfem/ gmm/
Date: Sun, 09 Oct 2016 13:49:29 -0000

Author: renard
Date: Sun Oct  9 15:49:28 2016
New Revision: 5396

URL: http://svn.gna.org/viewcvs/getfem?rev=5396&view=rev
Log:
small additional optimization

Modified:
    trunk/getfem/src/bgeot_geometric_trans.cc
    trunk/getfem/src/getfem/bgeot_geometric_trans.h
    trunk/getfem/src/getfem_generic_assembly.cc
    trunk/getfem/src/gmm/gmm_matrix.h

Modified: trunk/getfem/src/bgeot_geometric_trans.cc
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/bgeot_geometric_trans.cc?rev=5396&r1=5395&r2=5396&view=diff
==============================================================================
--- trunk/getfem/src/bgeot_geometric_trans.cc   (original)
+++ trunk/getfem/src/bgeot_geometric_trans.cc   Sun Oct  9 15:49:28 2016
@@ -51,46 +51,46 @@
   }
 
   void geotrans_interpolation_context::compute_J(void) const {
-    GMM_ASSERT1(have_G() && have_pgt(), "unable to compute B\n");
-
-
-    // size_type P = pgt_->structure()->dim();
-    // B_.resize(N(), P);
-    // if (P != N()) {
-    //   gmm::resize(CS,P,P);
-    //   gmm::mult(gmm::transposed(K()), K(), CS);
-    //   // gmm::abs below because on flat convexes determinant could be 
-1e-27.
-    //   J_ = ::sqrt(gmm::abs(gmm::lu_inverse(CS)));
-    //   gmm::mult(K(), CS, B_);
-    // } else {
-    //   gmm::copy(gmm::transposed(K()), B_);
-    //   J_ = gmm::abs(gmm::lu_inverse(B_));
-    // }
-    
-    
+    GMM_ASSERT1(have_G() && have_pgt(), "unable to compute J\n");
     size_type P = pgt_->structure()->dim();
     if (P != N()) {
-      gmm::resize(CS,P,P);
-      gmm::mult(gmm::transposed(K()), K(), CS);
+      B_factors.base_resize(P, P);
+      gmm::mult(gmm::transposed(K()), K(), B_factors);
+      ipvt.resize(P);
+      gmm::lu_factor(B_factors, ipvt);
       // gmm::abs below because on flat convexes determinant could be -1e-27.
-      J_ = ::sqrt(gmm::abs(gmm::lu_det(CS)));
-    }
-    else
-      J_ = gmm::abs(gmm::lu_det(K()));
+      J_ = ::sqrt(gmm::abs(gmm::lu_det(B_factors, ipvt)));
+    }
+    else {
+      // J_ = gmm::abs(gmm::lu_det(K()));
+      if (P <= 2) {
+       const scalar_type *p = &(K()(0,0));
+       if (P == 1) J_ = gmm::abs(*p);
+       else J_ = gmm::abs((*p) * (*(p+3)) - (*(p+1)) * (*(p+2)));
+      } else {
+       B_factors.base_resize(P, P);
+       gmm::copy(gmm::transposed(K()), B_factors);
+       ipvt.resize(P);
+       gmm::lu_factor(B_factors, ipvt);
+       J_ = gmm::abs(gmm::lu_det(B_factors, ipvt));
+      }
+    }
+    have_J_ = true;
   }
 
   const base_matrix& geotrans_interpolation_context::K() const {
     if (!have_K()) {
       GMM_ASSERT1(have_G() && have_pgt(), "unable to compute K\n");
       size_type P = pgt_->structure()->dim();
-      K_.resize(N(), P);
+      K_.base_resize(N(), P);
       if (have_pgp()) {
        gmm::mult(G(), pgp_->grad(ii_), K_);
       } else {
-       gmm::resize(PC, pgt()->nb_points(), P);
+       PC.base_resize(pgt()->nb_points(), P);
         pgt()->poly_vector_grad(xref(), PC);
         gmm::mult(G(), PC, K_);
       }
+      have_K_ = true;
     }
     return K_;
   }
@@ -99,17 +99,36 @@
     if (!have_B()) {
       GMM_ASSERT1(have_G() && have_pgt(), "unable to compute B\n");
       size_type P = pgt_->structure()->dim();
-      B_.resize(N(), P);
+      const base_matrix &KK = K();
+      B_.base_resize(N(), P);
       if (P != N()) {
-        gmm::resize(CS,P,P);
-        gmm::mult(gmm::transposed(K()), K(), CS);
-        // gmm::abs below because on flat convexes determinant could be -1e-27.
-        J_ = ::sqrt(gmm::abs(gmm::lu_inverse(CS)));
-        gmm::mult(K(), CS, B_);
+       if (!have_J_) compute_J();
+       PC.base_resize(P, P);
+        gmm::lu_inverse(B_factors, ipvt, PC);
+        gmm::mult(KK, PC, B_);
       } else {
-        gmm::copy(gmm::transposed(K()), B_);
-        J_ = gmm::abs(gmm::lu_inverse(B_));
+       if (P <= 2) {
+         if (P == 1) {
+           scalar_type det = KK(0, 0);
+           GMM_ASSERT1(det != scalar_type(0), "non invertible matrix");
+           B_(0, 0) = scalar_type(1)/det;
+           J_ = gmm::abs(det);
+         } else {
+           const scalar_type *p = &(KK(0,0));
+           scalar_type det = (*p) * (*(p+3)) - (*(p+1)) * (*(p+2));
+           GMM_ASSERT1(det != scalar_type(0), "non invertible matrix");
+           scalar_type *q = &(B_(0,0));
+           *q++ =  (*(p+3)) / det;  *q++ = -(*(p+2)) / det;
+           *q++ = -(*(p+1)) / det;  *q++ =  (*p) / det;
+           J_ = gmm::abs(det);
+         }
+       } else {
+         scalar_type det = J();
+         GMM_ASSERT1(det != scalar_type(0), "non invertible matrix");
+         gmm::lu_inverse(B_factors, ipvt, B_);
+       }
       }
+      have_B_ = true;
     }
     return B_;
   }
@@ -118,12 +137,13 @@
     if (!have_B3()) {
       const base_matrix &BB = B();
       size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
-      B3_.resize(N_*N_, P*P);
+      B3_.base_resize(N_*N_, P*P);
       for (short_type i = 0; i < P; ++i)
         for (short_type j = 0; j < P; ++j)
           for (short_type k = 0; k < N_; ++k)
             for (short_type l = 0; l < N_; ++l)
               B3_(k + N_*l, i + P*j) = BB(k, i) * BB(l, j);
+      have_B3_ = true;
     }
     return B3_;
   }
@@ -132,16 +152,16 @@
     if (!have_B32()) {
       const base_matrix &BB = B();
       size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
-      B32_.resize(N_*N_, P);
+      B32_.base_resize(N_*N_, P);
       if (!pgt()->is_linear()) {
         base_matrix B2(P*P, P), Htau(N_, P*P);
         if (have_pgp()) {
           gmm::mult(G(), pgp_->hessian(ii_), Htau);
         } else {
           /* very inefficient of course... */
-          base_matrix pc(pgt()->nb_points(), P*P);
-          pgt()->poly_vector_hess(xref(), pc);
-          gmm::mult(G(), pc, Htau);
+         PC.base_resize(pgt()->nb_points(), P*P);
+          pgt()->poly_vector_hess(xref(), PC);
+          gmm::mult(G(), PC, Htau);
         }
         for (short_type i = 0; i < P; ++i)
           for (short_type j = 0; j < P; ++j)
@@ -150,47 +170,47 @@
                 B2(i + P*j, k) += Htau(l, i + P*j) * BB(l,k);
         gmm::mult(B3(), B2, B32_);
       } else gmm::clear(B32_);
+      have_B32_ = true;
     }
     return B32_;
   }
 
  void geotrans_interpolation_context::set_ii(size_type ii__) {
-    if (ii_ == ii__) return;
-    if (have_K() && !pgt()->is_linear()) { K_.resize(0,0); }
-    if (have_B() && !pgt()->is_linear()) { B_.resize(0,0); }
-    if (have_B3() && !pgt()->is_linear()) {
-      B3_.resize(0,0); B32_.resize(0,0); }
-    if (J_ >= scalar_type(0) && !pgt()->is_linear()) J_ = scalar_type(-1);
-    xref_.clear(); xreal_.clear();
-    ii_=ii__;
-  }
+   if (ii_ == ii__) return;
+   if (pgt_ && !pgt()->is_linear())
+     { have_K_ = have_B_ = have_B3_ = have_B32_ = have_J_ = false; }
+   xref_.resize(0); xreal_.resize(0);
+   ii_=ii__;
+ }
 
   void geotrans_interpolation_context::set_xref(const base_node& P) {
     xref_ = P;
-    if (have_K() && !pgt()->is_linear()) { K_.resize(0,0); }
-    if (have_B() && !pgt()->is_linear()) { B_.resize(0,0); }
-    if (have_B3() && !pgt()->is_linear()) {
-      B3_.resize(0,0); B32_.resize(0,0); }
-    if (J_ >= scalar_type(0) && !pgt()->is_linear()) J_ = scalar_type(-1);
-    xreal_.clear(); ii_ = size_type(-1); pspt_ = 0;
+    if (pgt_ && !pgt()->is_linear())
+      { have_K_ = have_B_ = have_B3_ = have_B32_ = have_J_ = false; }
+    xreal_.resize(0); ii_ = size_type(-1); pspt_ = 0;
   }
 
   geotrans_interpolation_context::geotrans_interpolation_context() :
-    G_(0), pgt_(0), pgp_(0), pspt_(0), ii_(size_type(-1)), J_(-1) {}
+    G_(0), pgt_(0), pgp_(0), pspt_(0), ii_(size_type(-1)),
+    have_J_(false), have_B_(false), have_B3_(false), have_B32_(false),
+    have_K_(false) {}
   geotrans_interpolation_context::geotrans_interpolation_context
   (bgeot::pgeotrans_precomp pgp__, size_type ii__, const base_matrix& G__) :
     G_(&G__), pgt_(pgp__->get_trans()), pgp_(pgp__),
-    pspt_(pgp__->get_ppoint_tab()), ii_(ii__), J_(-1) {}
+    pspt_(pgp__->get_ppoint_tab()), ii_(ii__), have_J_(false), have_B_(false),
+    have_B3_(false), have_B32_(false), have_K_(false) {}
   geotrans_interpolation_context::geotrans_interpolation_context
   (bgeot::pgeometric_trans pgt__, bgeot::pstored_point_tab pspt__,
    size_type ii__,  const base_matrix& G__) :
     G_(&G__), pgt_(pgt__), pgp_(0),
-    pspt_(pspt__), ii_(ii__), J_(-1) {}
+    pspt_(pspt__), ii_(ii__), have_J_(false), have_B_(false), have_B3_(false),
+    have_B32_(false), have_K_(false) {}
   geotrans_interpolation_context::geotrans_interpolation_context
   (bgeot::pgeometric_trans pgt__, const base_node& xref__,
    const base_matrix& G__) :
     xref_(xref__), G_(&G__), pgt_(pgt__), pgp_(0), pspt_(0),
-    ii_(size_type(-1)), J_(-1) {}
+    ii_(size_type(-1)),have_J_(false), have_B_(false), have_B3_(false),
+    have_B32_(false), have_K_(false)  {}
 
 
   base_node geometric_trans::transform(const base_node &pt,
@@ -245,7 +265,7 @@
 
     virtual void poly_vector_grad(const base_node &pt, base_matrix &pc) const {
       FUNC PP;
-      pc.resize(nb_points(),dim());
+      pc.base_resize(nb_points(),dim());
       for (size_type i = 0; i < nb_points(); ++i)
         for (dim_type n = 0; n < dim(); ++n) {
           PP = trans[i];
@@ -259,7 +279,7 @@
                                   base_matrix &pc) const {
       FUNC PP;
       size_type nb_funcs=ind_ct.size();
-      pc.resize(nb_funcs,dim());
+      pc.base_resize(nb_funcs,dim());
       for (size_type i = 0; i < nb_funcs; ++i)
         for (dim_type n = 0; n < dim(); ++n) {
           PP = trans[ind_ct[i]];
@@ -270,7 +290,7 @@
 
     virtual void poly_vector_hess(const base_node &pt, base_matrix &pc) const {
       FUNC PP, QP;
-      pc.resize(nb_points(),dim()*dim());
+      pc.base_resize(nb_points(),dim()*dim());
       for (size_type i = 0; i < nb_points(); ++i)
         for (dim_type n = 0; n < dim(); ++n) {
           QP = trans[i]; QP.derivative(n);

Modified: trunk/getfem/src/getfem/bgeot_geometric_trans.h
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/getfem/bgeot_geometric_trans.h?rev=5396&r1=5395&r2=5396&view=diff
==============================================================================
--- trunk/getfem/src/getfem/bgeot_geometric_trans.h     (original)
+++ trunk/getfem/src/getfem/bgeot_geometric_trans.h     Sun Oct  9 15:49:28 2016
@@ -404,16 +404,18 @@
     pstored_point_tab pspt_; /** if pgp != 0, it is the same as pgp's one */
     size_type ii_; /** index of current point in the pgp */
     mutable scalar_type J_; /** Jacobian */
-    mutable base_matrix CS, PC;
+    mutable base_matrix PC, B_factors;
+    mutable std::vector<size_type> ipvt;
+    mutable bool have_J_, have_B_, have_B3_, have_B32_, have_K_;
     void compute_J(void) const;
   public:
     bool have_xref() const { return !xref_.empty(); }
     bool have_xreal() const { return !xreal_.empty(); }
     bool have_G() const { return G_ != 0; }
-    bool have_K() const { return !K_.empty(); }
-    bool have_B() const { return !B_.empty(); }
-    bool have_B3() const { return !B3_.empty(); }
-    bool have_B32() const { return !B32_.empty(); }
+    bool have_K() const { return have_K_; }
+    bool have_B() const { return have_B_; }
+    bool have_B3() const { return have_B3_; }
+    bool have_B32() const { return have_B32_; }
     bool have_pgt() const { return pgt_ != 0; }
     bool have_pgp() const { return pgp_ != 0; }
     /// coordinates of the current point, in the reference convex.
@@ -429,7 +431,7 @@
     /** matrix whose columns are the vertices of the convex */
     const base_matrix& G() const { return *G_; }
     /** get the Jacobian of the geometric trans (taken at point @c xref() ) */
-    scalar_type J() const { if (J_ < scalar_type(0)) compute_J(); return J_; }
+    scalar_type J() const { if (!have_J_) compute_J(); return J_; }
     size_type N() const { if (have_G()) return G().nrows();
       else if (have_xreal()) return xreal_.size();
       else GMM_ASSERT2(false, "cannot get N"); return 0; }

Modified: trunk/getfem/src/getfem_generic_assembly.cc
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/getfem_generic_assembly.cc?rev=5396&r1=5395&r2=5396&view=diff
==============================================================================
--- trunk/getfem/src/getfem_generic_assembly.cc (original)
+++ trunk/getfem/src/getfem_generic_assembly.cc Sun Oct  9 15:49:28 2016
@@ -3439,7 +3439,7 @@
     void do_transformation() {
       size_type nn = gmm::vect_size(coeff_in);
       if (M.size() == 0 || icv != ctx.convex_num() || &mf != *mf_M) {
-        gmm::resize(M, nn, nn);
+        M.base_resize(nn, nn);
         *mf_M = &mf; icv = ctx.convex_num();
         elemtrans->give_transformation(mf, icv, M);
       }
@@ -3840,7 +3840,7 @@
 
     void do_transformation(size_type n) {
       if (M.size() == 0 || icv != ctx.convex_num() || &mf != *mf_M) {
-        gmm::resize(M, n, n);
+        M.base_resize(n, n);
         *mf_M = &mf; icv = ctx.convex_num();
         elemtrans->give_transformation(mf, icv, M);
       }
@@ -5406,7 +5406,7 @@
     virtual int exec() {
       GA_DEBUG_INFO("Instruction: vector term assembly for fem variable");
       if (ipt == 0 || interpolate) {
-       gmm::resize(elem, t.size());
+       elem.resize(t.size());
        gmm::copy(gmm::scaled(t.as_vector(), coeff), elem);
       } else {
        gmm::add(gmm::scaled(t.as_vector(), coeff), elem);
@@ -5480,7 +5480,7 @@
     virtual int exec() {
       GA_DEBUG_INFO("Instruction: matrix term assembly");
       if (ipt == 0 || interpolate) {
-        gmm::resize(elem, t.size());
+        elem.resize(t.size());
         gmm::copy(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
       } else {
         gmm::add(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
@@ -5581,7 +5581,7 @@
       GA_DEBUG_INFO("Instruction: matrix term assembly for standard "
                    "scalar fems");
       if (ipt == 0) {
-       gmm::resize(elem, t.size());
+       elem.resize(t.size());
         gmm::copy(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
       } else {
         gmm::add(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
@@ -5644,7 +5644,7 @@
       GA_DEBUG_INFO("Instruction: matrix term assembly for standard "
                    "vector fems");
       if (ipt == 0) {
-       gmm::resize(elem, t.size());
+       elem.resize(t.size());
         gmm::copy(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
       } else {
         gmm::add(gmm::scaled(t.as_vector(), coeff*alpha1*alpha2), elem);
@@ -12339,7 +12339,7 @@
     getfem::base_vector loc_U;
     for (mr_visitor v(rg); !v.finished(); v.next()) {
       size_type nd = mf.nb_basic_dof_of_element(v.cv());
-      gmm::resize(loc_M, nd, nd); gmm::resize(loc_U, nd);
+      loc_M.base_resize(nd, nd); gmm::resize(loc_U, nd);
       gmm::sub_index J(mf.ind_basic_dof_of_element(v.cv()));
       gmm::copy(gmm::sub_matrix(M, J, J), loc_M);
       gmm::lu_solve(loc_M, loc_U, gmm::sub_vector(F, J));

Modified: trunk/getfem/src/gmm/gmm_matrix.h
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/gmm/gmm_matrix.h?rev=5396&r1=5395&r2=5396&view=diff
==============================================================================
--- trunk/getfem/src/gmm/gmm_matrix.h   (original)
+++ trunk/getfem/src/gmm/gmm_matrix.h   Sun Oct  9 15:49:28 2016
@@ -369,6 +369,7 @@
     const std::vector<T> &as_vector(void) const { return *this; }
 
     void resize(size_type, size_type);
+    void base_resize(size_type, size_type);
     void reshape(size_type, size_type);
     
     void fill(T a, T b = T(0));
@@ -387,6 +388,10 @@
     nbl = m; nbc = n;
   }
 
+  template<typename T> void dense_matrix<T>::base_resize(size_type m,
+                                                        size_type n)
+  { std::vector<T>::resize(n*m); nbl = m; nbc = n; }
+  
   template<typename T> void dense_matrix<T>::resize(size_type m, size_type n) {
     if (n*m > nbc*nbl) std::vector<T>::resize(n*m);
     if (m < nbl) {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]