dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #02807
Re: array(), getRow() etc
On Fri, 2006-06-30 at 16:41 +0200, Anders Logg wrote:
> On Fri, Jun 30, 2006 at 04:30:50PM +0200, Garth N. Wells wrote:
> > On Fri, 2006-06-30 at 16:00 +0200, Anders Logg wrote:
> > > On Fri, Jun 30, 2006 at 03:08:45PM +0200, Garth N. Wells wrote:
> > > > On Fri, 2006-06-30 at 12:29 +0200, Anders Logg wrote:
> > > > > On Fri, Jun 30, 2006 at 08:48:59AM +0200, Anders Logg wrote:
> > > > > > On Fri, Jun 30, 2006 at 12:32:25AM +0200, Garth N. Wells wrote:
> > > > > > > On Thu, 2006-06-29 at 20:20 +0200, Anders Logg wrote:
> > > > > > > > I've started trying to remove the PETSc ifdefs from the ODE solvers,
> > > > > > > > but ran into some problems. The ODE solver uses the calls
> > > > > > > >
> > > > > > > > Vector x;
> > > > > > > > real* xx = x.array();
> > > > > > > > // operate on xx
> > > > > > > > x.restore(xx);
> > > > > > > >
> > > > > > > > This is supported only by PETSc vectors.
> > > > > > > >
> > > > > > > > There are a couple of different solutions:
> > > > > > > >
> > > > > > > > 1. Don't use Vector::array().
> > > > > > > >
> > > > > > > > 2. Add Vector::array() to uBlas vectors.
> > > > > > > >
> > > > > > > > 3. Do 2 and add it to GenericVector as well.
> > > > > > > >
> > > > > > > > Any thoughts? I have a feeling 1 is the best solution, but it's also
> > > > > > > > the one that requires the most work (for me to rewrite the ODE
> > > > > > > > solvers).
> > > > > > > >
> > > > > > >
> > > > > > > I think that option 1 is best. I don't like options 2 & 3 as they take
> > > > > > > away the advantages of using uBlas. What exactly do you do with the
> > > > > > > Vector::array() in ode?
> > > > > >
> > > > > > The solution is (for some of the solvers) stored as a Vector u, but when
> > > > > > calling the user-supplied right-hand side f(u, t), the argument is
> > > > > > given as a plain C array since the user will often want to do a lot of
> > > > > > indexing of the vector in the definition of the right-hand side and I
> > > > > > suspect indexing is slow for PETSc vectors.
> > > > > >
> > > > > > > How fast are the PETSc functions VecGetValues
> > > > > > > and VecSetValue, and how much time is involved in calling
> > > > > > > VecAssemblyBegin() and VecAssemblyEnd() (which are currently called
> > > > > > > after every set)? I use Vector::array in the Cahn-Hilliard solver to do
> > > > > > > things like take the log of each term. Not sure how to do this
> > > > > > > efficiently without using array which will work for both PETSc and uBlas
> > > > > > > types.
> > > > > >
> > > > > > I'll make a small test to see how slow it really is.
> > > > >
> > > > > Here are some results. The timings are for setting and then accessing
> > > > > all elements in a vector of size 10000:
> > > > >
> > > > > Setting values in PETSc vector: 0.0708
> > > > > Accessing values in PETSc vector: 0.00031
> > > > > Setting values in uBlas vector: 1.42e-05
> > > > > Accessing values in uBlas vector: 4.6e-06
> > > > > Setting values in STL vector: 1.41e-05
> > > > > Accessing values in STL vector: 4.7e-06
> > > > > Setting values in C array: 1.4e-05
> > > > > Accessing values in C array: 1.41e-05
> > > > >
> > > > > Some conclusions:
> > > > >
> > > > > - Setting and accessing values element-wise in a PETSc array
> > > > > is terribly slow
> > > > >
> > > > > - uBlas, STL vector and C array are equally fast, don't know
> > > > > why access for C array is slower
> > > > >
> > > >
> > > > When I was first testing uBlas I saw that C arrays were often a bit
> > > > slower. I didn't understand why either.
> > > >
> > > >
> > > > > It seems the natural is to modify the interface for the ODE solver from
> > > > >
> > > > > void f(const real u[], real t, real y[]);
> > > > >
> > > > > to
> > > > >
> > > > > void f(const DenseVector& u, real t, DenseVector& y);
> > > > >
> > > > > Since the ODE solvers are currently not parallel anyway, I might as
> > > > > well use DenseVector in combination with the uBlas solvers. This
> > > > > should speed up the ODE solvers for small systems as well.
> > > > >
> > > >
> > > > For the future, it might be possible to create a uBlas vector that
> > > > addresses the array returned by PETScVector::array(). It's important
> > > > that we find a solution for manipulating array elements efficiently and
> > > > cleanly.
> > >
> > > DenseVector seems like a good option. It's the fastest and it works
> > > with some of the solvers.
> > >
> > > Maybe the array() should be special for the PETSc vector since that's
> > > the only place where it's needed?
> > >
> > > > > Garth, we need to extend the new uBlas solvers you added so that they
> > > > > work with a VirtualMatrix, that is, something which provides the
> > > > > function
> > > > >
> > > > > void mult(const DenseVector& x, DenseVector& y) const;
> > > > >
> > > > > Would that be much work to add?
> > > > >
> > > >
> > > > Should be OK.
> > >
> > > ok, I might try to fix it.
> > >
> >
> > I've had a quick look, and the only things that needs to be done are
> >
> > 1. Template the uBlasKrylovSolver solve functions,
> >
> > template <class M >
> > uint solve(const M& A, DenseVector& x, const DenseVector& b);
> >
> > I wanted to do this anyway as the solvers can also work with dense
> > matrices.
>
> I don't think we need to make templates (as usual...). I started
> looking at it and I've created an interface base class that specifies
> the interface for matrices that work with the uBlas Krylov solver: a
> size() function and a mult() function.
>
:)
No trying to frustrate you, but I was planning to make uBlasMatrix a
templated class as the code in uBlasSparseMatrix and Densematrix is 95%
identical. I'd then add
typedef uBlasMatrix<ublas_matrix> DenseMatrix;
typedef uBlasMatrix<ublas_sparse_matrix> uBlasSparseMatrix;
> > 2. Add a function uBlasSparseMatrix::mult_plus(const x, y) to compute y
> > += Ax
> >
> > 3. Use A.mult(x, y) in place of axpy_prod(A, x, y, true) and
> > A.mult_plus(x,y) in place of axpy_prod(A, x, y, false) in
> > uBlasKrylovSolver.
> >
> > 4. Make the uBlasKrylovSolver::mult() functions templates so that they
> > can accept ublas_vector. The alternative is to use Densevector in place
> > of ublas_vector in uBlasKrylovSolver. I didn't do this originally as the
> > DenseVector constructor calls clear() which is not needed and does
> > involve some overhead.
>
> Is it noticeable?
>
It's equivalent to assigning a value to all vector elements.
> > 4. Add the class uBlasVirtualMatrix.
>
> I called it uBlasKrylovMatrix and will rename VirtualMatrix to
> PETScKrylovMatrix. Then we can have a typedef for VirtualMatrix
> depending on the default matrix type.
>
OK.
On another topic, I don't think that we should implement a uBlas sparse
direct solver (nor do I want to). It's way too complicated to make it
fast. There are however bindings for uBlas to UMFPACK which would be a
really simple way to have a good direct solver. UMFPACK is available as
a Debian package so it's easy to install and it's one the fastest LU
solvers around. What do you think?
BTW, can we fix the mailing list so I don't get two copies of
everything?
Garth
> /Anders
>
> > 5. Generalise the preconditioner.
> >
> > Garth
> >
> > > /Anders
> >
> _______________________________________________
> DOLFIN-dev mailing list
> DOLFIN-dev@xxxxxxxxxx
> http://www.fenics.org/mailman/listinfo/dolfin-dev
Follow ups
References