Esempio n. 1
0
  ESymSolverStatus Ma27TSolverInterface::Backsolve(Index nrhs,
      double *rhs_vals)
  {
    DBG_START_METH("Ma27TSolverInterface::Backsolve",dbg_verbosity);
    IpData().TimingStats().LinearSystemBackSolve().Start();

    ipfint N=dim_;
    double* W = new double[maxfrt_];
    ipfint* IW1 = new ipfint[nsteps_];

    // For each right hand side, call MA27CD
    for(Index irhs=0; irhs<nrhs; irhs++) {
      if (DBG_VERBOSITY()>=2) {
        for (Index i=0; i<dim_; i++) {
          DBG_PRINT((2, "rhs[%5d] = %23.15e\n", i, rhs_vals[irhs*dim_+i]));
        }
      }

      F77_FUNC(ma27cd,MA27CD)(&N, a_, &la_, iw_, &liw_, W, &maxfrt_,
                              &rhs_vals[irhs*dim_], IW1, &nsteps_,
                              icntl_, cntl_);

      if (DBG_VERBOSITY()>=2) {
        for (Index i=0; i<dim_; i++) {
          DBG_PRINT((2, "sol[%5d] = %23.15e\n", i, rhs_vals[irhs*dim_+i]));
        }
      }
    }
    delete [] W;
    delete [] IW1;

    IpData().TimingStats().LinearSystemBackSolve().End();
    return SYMSOLVER_SUCCESS;
  }
ESymSolverStatus Ma57TSolverInterface::Backsolve(
    Index     nrhs,
    double    *rhs_vals)
{
    DBG_START_METH("Ma27TSolverInterface::Backsolve",dbg_verbosity);
    if (HaveIpData()) {
        IpData().TimingStats().LinearSystemBackSolve().Start();
    }

    ipfint  n      = dim_;
    ipfint  job    = 1;

    ipfint  nrhs_X = nrhs;
    ipfint  lrhs   = n;

    ipfint  lwork;
    double* work;

    lwork = n * nrhs;
    work = new double[lwork];

    // For each right hand side, call MA57CD
    // XXX MH: MA57 can do several RHSs; just do one solve...
    // AW: Ok is the following correct?
    if (DBG_VERBOSITY()>=2) {
        for (Index irhs=0; irhs<nrhs; irhs++) {
            for (Index i=0; i<dim_; i++) {
                DBG_PRINT((2, "rhs[%2d,%5d] = %23.15e\n", irhs, i, rhs_vals[irhs*dim_+i]));
            }
        }
    }

    F77_FUNC (ma57cd, MA57CD)
    (&job, &n, wd_fact_, &wd_lfact_, wd_ifact_, &wd_lifact_,
     &nrhs_X, rhs_vals, &lrhs,
     work, &lwork, wd_iwork_,
     wd_icntl_, wd_info_);

    if (wd_info_[0] != 0)
        Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA,
                       "Error in MA57CD:  %d.\n", wd_info_[0]);

    if (DBG_VERBOSITY()>=2) {
        for (Index irhs=0; irhs<nrhs; irhs++) {
            for (Index i=0; i<dim_; i++) {
                DBG_PRINT((2, "sol[%2d,%5d] = %23.15e\n", irhs, i, rhs_vals[irhs*dim_+i]));
            }
        }
    }

    delete [] work;

    if (HaveIpData()) {
        IpData().TimingStats().LinearSystemBackSolve().End();
    }
    return SYMSOLVER_SUCCESS;
}
Esempio n. 3
0
  void TripletToCSRConverter::ConvertValues(Index nonzeros_triplet,
      const Number* a_triplet,
      Index nonzeros_compressed,
      Number* a_compressed)
  {
    DBG_START_METH("TSymLinearSolver::ConvertValues",
                   dbg_verbosity);

    DBG_ASSERT(initialized_);

    DBG_ASSERT(nonzeros_triplet_==nonzeros_triplet);
    DBG_ASSERT(nonzeros_compressed_==nonzeros_compressed);

    for (Index i=0; i<nonzeros_compressed_; i++) {
      a_compressed[i] = a_triplet[ipos_first_[i]];
    }
    for (Index i=0; i<num_doubles_; i++) {
      a_compressed[ipos_double_compressed_[i]] +=
        a_triplet[ipos_double_triplet_[i]];
    }

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<nonzeros_triplet; i++) {
        DBG_PRINT((2, "atriplet[%5d] = %24.16e\n", i, a_triplet[i]));
      }
      for (Index i=0; i<nonzeros_compressed; i++) {
        DBG_PRINT((2, "acompre[%5d] = %24.16e\n", i, a_compressed[i]));
      }
    }
  }
Esempio n. 4
0
  void TSymLinearSolver::GiveMatrixToSolver(bool new_matrix,
      const SymMatrix& sym_A)
  {
    DBG_START_METH("TSymLinearSolver::GiveMatrixToSolver",dbg_verbosity);
    DBG_PRINT((1,"new_matrix = %d\n",new_matrix));

    double* pa = solver_interface_->GetValuesArrayPtr();
    double* atriplet;

    if (matrix_format_!=SparseSymLinearSolverInterface::Triplet_Format) {
      atriplet = new double[nonzeros_triplet_];
    }
    else {
      atriplet = pa;
    }

    //DBG_PRINT_MATRIX(3, "Aunscaled", sym_A);
    TripletHelper::FillValues(nonzeros_triplet_, sym_A, atriplet);
    if (DBG_VERBOSITY()>=3) {
      for (Index i=0; i<nonzeros_triplet_; i++) {
        DBG_PRINT((3, "KKTunscaled(%6d,%6d) = %24.16e\n", airn_[i], ajcn_[i], atriplet[i]));
      }
    }

    if (use_scaling_) {
      IpData().TimingStats().LinearSystemScaling().Start();
      DBG_ASSERT(scaling_factors_);
      if (new_matrix || just_switched_on_scaling_) {
        // only compute scaling factors if the matrix has not been
        // changed since the last call to this method
        bool retval =
          scaling_method_->ComputeSymTScalingFactors(dim_, nonzeros_triplet_,
              airn_, ajcn_,
              atriplet, scaling_factors_);
        if (!retval) {
          Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA,
                         "Error during computation of scaling factors.\n");
          THROW_EXCEPTION(ERROR_IN_LINEAR_SCALING_METHOD, "scaling_method_->ComputeSymTScalingFactors returned false.")
        }
        // complain if not in debug mode
        if (Jnlst().ProduceOutput(J_MOREVECTOR, J_LINEAR_ALGEBRA)) {
          for (Index i=0; i<dim_; i++) {
            Jnlst().Printf(J_MOREVECTOR, J_LINEAR_ALGEBRA,
                           "scaling factor[%6d] = %22.17e\n",
                           i, scaling_factors_[i]);
          }
        }
        just_switched_on_scaling_ = false;
      }
Esempio n. 5
0
  void CachedResults<T>::DebugPrintCachedResults() const
  {
#ifdef IP_DEBUG_CACHE
    DBG_START_METH("CachedResults<T>::DebugPrintCachedResults", dbg_verbosity);
    if (DBG_VERBOSITY()>=2 ) {
      if (!cached_results_) {
        DBG_PRINT((2,"Currentlt no cached results:\n"));
      }
      else {
        typename std::list< DependentResult<T>* >::const_iterator iter;
        DBG_PRINT((2,"Current set of cached results:\n"));
        for (iter = cached_results_->begin(); iter != cached_results_->end(); iter++) {
          DBG_PRINT((2,"  DependentResult:0x%x\n", (*iter)));
        }
      }
    }
#endif

  }
  /* inline methods */
  inline
  Observer::~Observer()
  {
#ifdef IP_DEBUG_OBSERVER
    DBG_START_METH("Observer::~Observer", dbg_verbosity);
    if (DBG_VERBOSITY()>=1) {
      for (Index i=0; i<(Index)subjects_.size(); i++) {
        DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
      }
    }
#endif
    // Detach all subjects
    for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
#ifdef IP_DEBUG_OBSERVER
      DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
#endif

      RequestDetach(NT_All, subjects_[i]);
    }
  }
Esempio n. 7
0
  bool Mc19TSymScalingMethod::ComputeSymTScalingFactors(Index n,
      Index nnz,
      const ipfint* airn,
      const ipfint* ajcn,
      const double* a,
      double* scaling_factors)
  {
    DBG_START_METH("Mc19TSymScalingMethod::ComputeSymTScalingFactors",
                   dbg_verbosity);

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<nnz; i++) {
        DBG_PRINT((2, "%5d A[%5d,%5d] = %23.15e\n", i, airn[i], ajcn[i], a[i]));
      }
    }
    // First copy the symmetric matrix into an unsymmetric (MA28)
    // format matrix
    ipfint* AIRN2 = new ipfint[2*nnz];
    ipfint* AJCN2 = new ipfint[2*nnz];
    double* A2 = new double[2*nnz];
    ipfint nnz2=0;
    for (Index i=0; i<nnz; i++) {
      if (airn[i]==ajcn[i]) {
        AIRN2[nnz2] = airn[i];
        AJCN2[nnz2] = ajcn[i];
        /*
        // ToDo decide if there should be a cut-off for small values in A
        // probably based on maximal element in A
        // DELETEME
        if (fabs(a[i])<1e-10) {
          A2[nnz2] = 0.;
        }
        else {
          A2[nnz2] = a[i];
               }
        */
        A2[nnz2] = a[i];
        nnz2++;
      }
      else {
        AIRN2[nnz2] = airn[i];
        AJCN2[nnz2] = ajcn[i];
        /*
        // DELETEME
        if (fabs(a[i])<1e-10) {
          A2[nnz2] = 0.;
        }
        else {
          A2[nnz2] = a[i];
        }
        */
        A2[nnz2] = a[i];
        nnz2++;
        AIRN2[nnz2] = ajcn[i];
        AJCN2[nnz2] = airn[i];
        /*
        // DELETEME
        if (fabs(a[i])<1e-10) {
          A2[nnz2] = 0.;
        }
        else {
          A2[nnz2] = a[i];
        }
        */
        A2[nnz2] = a[i];
        nnz2++;
      }
    }

    if (DBG_VERBOSITY()>=3) {
      for (Index i=0; i<nnz2; i++) {
        DBG_PRINT((3, "A2[%5d] = %23.15e\n", i, A2[i]));
      }
    }

    // Call MC19 to get the scaling factors (for the matrix in the
    // general format)
    float* R = new float[n];
    float* C = new float[n];
    float* W = new float[5*n];
    F77_FUNC(mc19ad,MC19AD)(&n, &nnz2, A2, AIRN2, AJCN2, R, C, W);
    delete[] W;

    if (DBG_VERBOSITY()>=3) {
      for (Index i=0; i<n; i++) {
        DBG_PRINT((3, "R[%5d] = %23.15e  C[%5d] = %23.15e\n",
                   i, R[i], i, C[i]));
      }
    }

    // Get the symmetric scaling factors as mean of the general ones
    // If some of the entries in A2 are too large, the scaling factors
    // are NaN.  Here, we check for this and return no scaling factors
    // if that is the case
    Number sum=0.;
    for (Index i=0; i<n; i++) {
      scaling_factors[i] = exp((double)((R[i]+C[i])/2.));
      sum += scaling_factors[i];
    }
    if (!IsFiniteNumber(sum)) {
      Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA,
                     "Scaling factors are invalid - setting them all to 1.\n");
      for (Index i=0; i<n; i++) {
        scaling_factors[i] = 1.;
      }
    }

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<n; i++) {
        DBG_PRINT((2, "scaling_factors[%5d] = %23.15e\n",
                   i, scaling_factors[i]));
      }
    }

    // Clean up
    delete[] C;
    delete[] R;
    delete[] A2;
    delete[] AIRN2;
    delete[] AJCN2;

    return true;
  }
Esempio n. 8
0
  Index TripletToCSRConverter::InitializeConverter(Index dim, Index nonzeros,
      const Index* airn,
      const Index* ajcn)
  {
    DBG_START_METH("TSymLinearSolver::InitializeStructure",
                   dbg_verbosity);

    DBG_ASSERT(dim>0);
    DBG_ASSERT(nonzeros>0);

    delete[] ia_;
    delete[] ja_;
    delete[] ipos_first_;
    delete[] ipos_double_triplet_;
    delete[] ipos_double_compressed_;

    dim_ = dim;
    nonzeros_triplet_ = nonzeros;

    // Create a list with all triplet entries
    std::list<TripletEntry> entry_list(nonzeros);
    std::list<TripletEntry>::iterator list_iterator = entry_list.begin();
    for (Index i=0; i<nonzeros; i++) {
      list_iterator->Set(airn[i], ajcn[i], i);
      list_iterator++;
    }
    DBG_ASSERT(list_iterator == entry_list.end());

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<nonzeros; i++) {
        DBG_PRINT((2, "airn[%5d] = %5d acjn[%5d] = %5d\n", i, airn[i], i, ajcn[i]));
      }
    }

    // sort the list
    entry_list.sort();

    // Now got through the list and compute ipos_ arrays and the
    // number of elements in the compressed format
    Index* ja_tmp = new Index[nonzeros];    // overestimate memory requirement
    Index* rc_tmp = NULL;
    if (hf_ == Full_Format) {
      rc_tmp = new Index[dim_+1];
    }
    ia_ = new Index[dim_+1];
    Index* ipos_first_tmp = new Index[nonzeros];  // overestimate memory requirement
    Index* ipos_double_triplet_tmp = new Index[nonzeros];  // overestimate memory requirement
    Index* ipos_double_compressed_tmp = new Index[nonzeros];  // overestimate memory requirement

    Index nonzeros_compressed_full = 0;
    nonzeros_compressed_ = 0;
    Index cur_row = 1;

    if (hf_ == Full_Format) {
      // Zero row counts
      for (Index i=0; i<dim_+1; i++) {
        rc_tmp[i] = 0;
      }
    }

    // Take care of possible emply rows
    list_iterator = entry_list.begin();
    while (cur_row < list_iterator->IRow()) {
      ia_[cur_row-1] = 0;
      cur_row++;
    }
    ia_[cur_row-1] = 0;
    ja_tmp[0] = list_iterator->JCol();
    ipos_first_tmp[0] = list_iterator->PosTriplet();
    if (hf_ == Full_Format) {
      // Count in both lower and upper triangles. Count diagonal only once.
      nonzeros_compressed_full++;
      rc_tmp[cur_row-1]++;
      if (cur_row!=list_iterator->JCol()) {
        nonzeros_compressed_full++;
        rc_tmp[list_iterator->JCol()-1]++;
      }
    }

    list_iterator++;
    Index idouble = 0;
    Index idouble_full = 0;
    while (list_iterator != entry_list.end()) {
      Index irow = list_iterator->IRow();
      Index jcol = list_iterator->JCol();
      if (cur_row == irow && ja_tmp[nonzeros_compressed_] == jcol) {
        // This element appears repeatedly, add to the double list
        ipos_double_triplet_tmp[idouble] = list_iterator->PosTriplet();
        ipos_double_compressed_tmp[idouble] = nonzeros_compressed_;
        idouble++;
        idouble_full++;
        if (hf_==Full_Format && irow!=jcol) {
          idouble_full++;
        }
      }
      else {
        // This is a new element
        if (hf_==Full_Format) {
          // Count in both lower and upper triangles. Count diagonal only once.
          nonzeros_compressed_full++;
          rc_tmp[jcol-1]++;
          if (irow!=jcol) {
            nonzeros_compressed_full++;
            rc_tmp[irow-1]++;
          }
        }
        nonzeros_compressed_++;
        ja_tmp[nonzeros_compressed_] = jcol;
        ipos_first_tmp[nonzeros_compressed_] = list_iterator->PosTriplet();
        if (cur_row != irow) {
          // this is in a new row

          ia_[cur_row] = nonzeros_compressed_;
          cur_row++;
        }
      }

      list_iterator++;
    }
    nonzeros_compressed_++;
    for (Index i=cur_row; i<=dim_; i++) {
      ia_[i] = nonzeros_compressed_;
    }
    DBG_ASSERT(idouble == nonzeros_triplet_-nonzeros_compressed_);

    // Now copy the ja_tmp array to the (shorter) final one and make
    // sure that the correct offset is used
    if (hf_==Triangular_Format) {
      ja_ = new Index[nonzeros_compressed_];
      if (offset_==0) {
        for (Index i=0; i<nonzeros_compressed_; i++) {
          ja_[i] = ja_tmp[i] - 1;
        }
      }
      else {
        for (Index i=0; i<nonzeros_compressed_; i++) {
          ja_[i] = ja_tmp[i];
        }
        for (Index i=0; i<=dim_; i++) {
          ia_[i] = ia_[i] + 1;
        }
      }
      delete[] ja_tmp;

      // Reallocate memory for the "first" array
      ipos_first_ = new Index[nonzeros_compressed_];
      for (Index i=0; i<nonzeros_compressed_; i++) {
        ipos_first_[i] = ipos_first_tmp[i];
      }
      delete[] ipos_first_tmp;

      // Reallocate memory for the "double" arrays
      ipos_double_triplet_ = new Index[idouble];
      ipos_double_compressed_ = new Index[idouble];
      for (Index i=0; i<idouble; i++) {
        ipos_double_triplet_[i] = ipos_double_triplet_tmp[i];
        ipos_double_compressed_[i] = ipos_double_compressed_tmp[i];
      }
      delete[] ipos_double_triplet_tmp;
      delete[] ipos_double_compressed_tmp;
      num_doubles_ = nonzeros_triplet_ - nonzeros_compressed_;
    }
    else { // hf_==Full_Format

      // Setup ia_tmp to contain insert position for column i as ia_tmp[i+1]
      Index *ia_tmp = new Index[dim_+1];
      ia_tmp[0] = 0;
      ia_tmp[1] = 0;
      for (Index i=1; i<dim_; i++) {
        ia_tmp[i+1] = ia_tmp[i] + rc_tmp[i-1];
      }
      delete[] rc_tmp;

      // Loop over elements of matrix, copying them and duplicating as required
      ja_ = new Index[nonzeros_compressed_full];
      ipos_first_ = new Index[nonzeros_compressed_full];
      ipos_double_triplet_ = new Index[idouble_full];
      ipos_double_compressed_ = new Index[idouble_full];
      Index jd1=0; // Entry into ipos_double_compressed_tmp
      Index jd2=0; // Entry into ipos_double_compressed_
      for (Index i=0; i<dim_; i++) {
        for (Index j=ia_[i]; j<ia_[i+1]; j++) {
          Index jrow = ja_tmp[j]-1;
          ja_[ia_tmp[i+1]] = jrow + offset_;
          ipos_first_[ia_tmp[i+1]] = ipos_first_tmp[j];
          while (jd1<idouble && j==ipos_double_compressed_tmp[jd1]) {
            ipos_double_triplet_[jd2] = ipos_double_triplet_tmp[jd1];
            ipos_double_compressed_[jd2] = ia_tmp[i+1];
            jd2++;
            if (jrow!=i) {
              ipos_double_triplet_[jd2] = ipos_double_triplet_tmp[jd1];
              ipos_double_compressed_[jd2] = ia_tmp[jrow+1];
            }
            jd1++;
          }
          ia_tmp[i+1]++;
          if (jrow!=i) {
            ja_[ia_tmp[jrow+1]] = i + offset_;
            ipos_first_[ia_tmp[jrow+1]] = ipos_first_tmp[j];
            ia_tmp[jrow+1]++;
          }
        }
      }
      delete[] ja_tmp;
      delete[] ipos_first_tmp;
      delete[] ipos_double_triplet_tmp;
      delete[] ipos_double_compressed_tmp;

      // Copy ia_tmp to ia_ with offset_ adjustment
      for (Index i=0; i<dim_+1; i++) {
        ia_[i] = ia_tmp[i] + offset_;
      }
      delete[] ia_tmp;

      // Set nonzeros_compressed_ to correct size
      nonzeros_compressed_ = nonzeros_compressed_full;
      num_doubles_ = idouble_full;
    }

    initialized_ = true;

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<=dim_; i++) {
        DBG_PRINT((2, "ia[%5d] = %5d\n", i, ia_[i]));
      }
      for (Index i=0; i<nonzeros_compressed_; i++) {
        DBG_PRINT((2, "ja[%5d] = %5d ipos_first[%5d] = %5d\n", i, ja_[i], i, ipos_first_[i]));
      }
      for (Index i=0; i<nonzeros_triplet_-nonzeros_compressed_; i++) {
        DBG_PRINT((2, "ipos_double_triplet[%5d] = %5d ipos_double_compressed[%5d] = %5d\n", i, ipos_double_triplet_[i], i, ipos_double_compressed_[i]));
      }
    }

    return nonzeros_compressed_;
  }
  Index TripletToCSRConverter::InitializeConverter(Index dim, Index nonzeros,
      const Index* airn,
      const Index* ajcn)
  {
    DBG_START_METH("TSymLinearSolver::InitializeStructure",
                   dbg_verbosity);

    DBG_ASSERT(dim>0);
    DBG_ASSERT(nonzeros>0);

    delete[] ia_;
    delete[] ja_;
    delete[] ipos_first_;
    delete[] ipos_double_triplet_;
    delete[] ipos_double_compressed_;

    dim_ = dim;
    nonzeros_triplet_ = nonzeros;

    // Create a list with all triplet entries
    std::list<TripletEntry> entry_list(nonzeros);
    std::list<TripletEntry>::iterator list_iterator = entry_list.begin();
    for (Index i=0; i<nonzeros; i++) {
      list_iterator->Set(airn[i], ajcn[i], i);
      ++list_iterator;
    }
    DBG_ASSERT(list_iterator == entry_list.end());

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<nonzeros; i++) {
        DBG_PRINT((2, "airn[%5d] = %5d acjn[%5d] = %5d\n", i, airn[i], i, ajcn[i]));
      }
    }

    // sort the list
    entry_list.sort();

    // Now got through the list and compute ipos_ arrays and the
    // number of elements in the compressed format
    Index* ja_tmp = new Index[nonzeros];    // overestimate memory requirement
    ia_ = new Index[dim_+1];
    Index* ipos_first_tmp = new Index[nonzeros];  // overestimate memory requirement
    Index* ipos_double_triplet_tmp = new Index[nonzeros];  // overestimate memory requirement
    Index* ipos_double_compressed_tmp = new Index[nonzeros];  // overestimate memory requirement

    nonzeros_compressed_ = 0;
    Index cur_row = 1;

    // The first element must be the first diagonal element
    list_iterator = entry_list.begin();
    DBG_ASSERT(list_iterator->IRow()==1);
    DBG_ASSERT(list_iterator->JCol()==1);
    ia_[0] = 0;
    ja_tmp[0] = 1;
    ipos_first_tmp[0] = list_iterator->PosTriplet();

    ++list_iterator;
    Index idouble = 0;
    while (list_iterator != entry_list.end()) {
      Index irow = list_iterator->IRow();
      Index jcol = list_iterator->JCol();
      if (cur_row == irow && ja_tmp[nonzeros_compressed_] == jcol) {
        // This element appears repeatedly, add to the double list
        ipos_double_triplet_tmp[idouble] = list_iterator->PosTriplet();
        ipos_double_compressed_tmp[idouble] = nonzeros_compressed_;
        idouble++;
      }
      else {
        // This is a new element
        nonzeros_compressed_++;
        ja_tmp[nonzeros_compressed_] = jcol;
        ipos_first_tmp[nonzeros_compressed_] = list_iterator->PosTriplet();
        if (cur_row != irow) {
          // this is in a new row

          // make sure that the diagonal element is given and that no
          // row is omitted
          DBG_ASSERT(irow==jcol);
          DBG_ASSERT(cur_row+1==irow);
          ia_[cur_row] = nonzeros_compressed_;
          cur_row++;
        }
      }

      ++list_iterator;
    }
    nonzeros_compressed_++;
    ia_[dim_] = nonzeros_compressed_;

    DBG_ASSERT(cur_row == dim_);
    DBG_ASSERT(idouble == nonzeros_triplet_-nonzeros_compressed_);

    // Now copy the ja_tmp array to the (shorter) final one and make
    // sure that the correct offset is used
    ja_ = new Index[nonzeros_compressed_];
    if (offset_==0) {
      for (Index i=0; i<nonzeros_compressed_; i++) {
        ja_[i] = ja_tmp[i] - 1;
      }
    }
    else {
      for (Index i=0; i<nonzeros_compressed_; i++) {
        ja_[i] = ja_tmp[i];
      }
      for (Index i=0; i<=dim_; i++) {
        ia_[i] = ia_[i] + 1;
      }
    }
    delete[] ja_tmp;

    // Reallocate memory for the "first" array
    ipos_first_ = new Index[nonzeros_compressed_];
    for (Index i=0; i<nonzeros_compressed_; i++) {
      ipos_first_[i] = ipos_first_tmp[i];
    }
    delete[] ipos_first_tmp;

    // Reallocate memory for the "double" arrays
    ipos_double_triplet_ = new Index[idouble];
    ipos_double_compressed_ = new Index[idouble];
    for (Index i=0; i<idouble; i++) {
      ipos_double_triplet_[i] = ipos_double_triplet_tmp[i];
      ipos_double_compressed_[i] = ipos_double_compressed_tmp[i];
    }
    delete[] ipos_double_triplet_tmp;
    delete[] ipos_double_compressed_tmp;

    initialized_ = true;

    if (DBG_VERBOSITY()>=2) {
      for (Index i=0; i<=dim_; i++) {
        DBG_PRINT((2, "ia[%5d] = %5d\n", i, ia_[i]));
      }
      for (Index i=0; i<nonzeros_compressed_; i++) {
        DBG_PRINT((2, "ja[%5d] = %5d ipos_first[%5d] = %5d\n", i, ja_[i], i, ipos_first_[i]));
      }
      for (Index i=0; i<nonzeros_triplet_-nonzeros_compressed_; i++) {
        DBG_PRINT((2, "ipos_double_triplet[%5d] = %5d ipos_double_compressed[%5d] = %5d\n", i, ipos_double_triplet_[i], i, ipos_double_compressed_[i]));
      }
    }

    return nonzeros_compressed_;
  }