Merge lp:~jobh/dolfin/fast-array into lp:~fenics-core/dolfin/trunk

Proposed by Joachim Haga
Status: Merged
Merged at revision: 6629
Proposed branch: lp:~jobh/dolfin/fast-array
Merge into: lp:~fenics-core/dolfin/trunk
Diff against target: 680 lines (+116/-168)
18 files modified
dolfin/adaptivity/TimeSeries.cpp (+5/-10)
dolfin/adaptivity/TimeSeries.h (+5/-5)
dolfin/ale/HarmonicSmoothing.cpp (+1/-1)
dolfin/common/Array.h (+68/-115)
dolfin/function/Function.cpp (+2/-2)
dolfin/graph/ZoltanInterface.cpp (+1/-1)
dolfin/io/BinaryFile.cpp (+2/-2)
dolfin/io/XMLFunctionData.cpp (+3/-3)
dolfin/io/XMLVector.cpp (+1/-1)
dolfin/la/EpetraVector.cpp (+2/-2)
dolfin/la/MUMPSLUSolver.cpp (+5/-5)
dolfin/la/PETScVector.cpp (+4/-4)
dolfin/mesh/MeshSmoothing.cpp (+1/-2)
dolfin/mesh/SubDomain.cpp (+3/-6)
dolfin/swig/common/post.i (+2/-4)
dolfin/swig/la/la_get_set_items.i (+2/-2)
dolfin/swig/typemaps/array.i (+2/-2)
site-packages/dolfin/compilemodules/compilemodule.py (+7/-1)
To merge this branch: bzr merge lp:~jobh/dolfin/fast-array
Reviewer Review Type Date Requested Status
Registry Administrators Pending
Review via email: mp+94467@code.launchpad.net

Description of the change

Changes Array from shared (using boost::shared_array) to a simpler representation. This change makes Poisson assembly 35% faster.

Creating a shared_array pointer requires heap allocations, and a lot of the time in assemble was spent just wrapping plain pointers in arrays. Furthermore, the shared semantics weren't used -- and if required the Array can be assigned to a shared_ptr.

Since this changes the binary interface to compiled modules, I added an interface version number (apart from the dolfin version number, which has more to do with the release schedule). Therefore instant modules will be recompiled.

To post a comment you must log in.
Revision history for this message
Garth Wells (garth-wells) wrote :

Where in the code were the most Arrays being created?

Revision history for this message
Joachim Haga (jobh) wrote :

In GenericFunction::evaluate, via the chain

Assembler::assemble_cells
UFC::update
Expression::restrict
GenericFunction::restrict_as_ufc
GenericFunction::evaluate <===
ffc_form_xxx

-j.

On 24 February 2012 13:34, Garth Wells <email address hidden> wrote:

> Where in the code were the most Arrays being created?
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> You are the owner of lp:~jobh/dolfin/fast-array.
>

Revision history for this message
Joachim Haga (jobh) wrote :

On 24 February 2012 13:34, Garth Wells <email address hidden> wrote:

> Where in the code were the most Arrays being created?
>

I wrote:

> In GenericFunction::evaluate, via the chain
>
> Assembler::assemble_cells
> UFC::update
> Expression::restrict
>

... and indeed it's the rhs that involves an expression that's faster:
f = Expression("...")
L = f*v*dx
b = assemble(L)

goes from 8.0s on 64x64x64 to 2.7s. This accounts for most (all?) of the
35% speed-up for A and b combined.

-j.

Revision history for this message
Garth Wells (garth-wells) wrote :

I'm not keen on ownership flags - they were a real mess before and it's been a lot better since we go rid of them.

Would be it be possible to (1) re-use the Array so we avoid dynamic allocation or (2) have an Array-like structure that always owns the data? The class Array was introduced to better interface with Python, but I recall that we later became aware that the Numpy interface has has a flag to prevent resizing, which would make typemaps more robust.

Revision history for this message
Joachim Haga (jobh) wrote :

I'd opine that the easiest would be to make array never own the data,
rather than always own the data. In that way, it can wrap anything.

* TimeSeries returns (owned) Arrays in two places. These could return
references to its own data (const vector<double>&), that would save a copy
(they are currently copied twice, once into an owned Array, then again in
swig into a numpy array). But maybe the amount of data returned is small,
in which case a vector<double> will be fine.

* Can't support resize() without ownership, so everywhere resize is used on
a reference argument should pass a vector<double>& instead. I think this is
a few places only.

At that point, Array will be a plain wrapper of others' data.

As for your (1), it might well be possible (keep a scratch array in the
GenericFunction class perhaps). But the thing is, the shared version was no
more safe. You can't keep a reference to an Array because you don't know if
it's shared or just wrapping data that will be deleted from under you. It
was "shared or borrowed" rather than "owned or borrowed", only without the
flag to tell the cases apart.

-j.

On 24 February 2012 19:37, Garth Wells <email address hidden> wrote:

> I'm not keen on ownership flags - they were a real mess before and it's
> been a lot better since we go rid of them.
>
> Would be it be possible to (1) re-use the Array so we avoid dynamic
> allocation or (2) have an Array-like structure that always owns the data?
> The class Array was introduced to better interface with Python, but I
> recall that we later became aware that the Numpy interface has has a flag
> to prevent resizing, which would make typemaps more robust.
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> You are the owner of lp:~jobh/dolfin/fast-array.
>

lp:~jobh/dolfin/fast-array updated
6592. By Joachim Haga

Compilation fix (initialisation order, with -Wall -Werror)

Revision history for this message
Anders Logg (logg) wrote :

On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
> I'd opine that the easiest would be to make array never own the data,
> rather than always own the data. In that way, it can wrap anything.
>
> * TimeSeries returns (owned) Arrays in two places. These could
> return references to its own data (const vector<double>&), that
> would save a copy (they are currently copied twice, once into an
> owned Array, then again in swig into a numpy array). But maybe the
> amount of data returned is small, in which case a vector<double>
> will be fine.

The return of arrays from TimeSeries is typically not performance
critical so a copy is fine (which it already is).

> * Can't support resize() without ownership, so everywhere resize is
> used on a reference argument should pass a vector<double>&
> instead. I think this is a few places only.
>
> At that point, Array will be a plain wrapper of others' data.
>
> As for your (1), it might well be possible (keep a scratch array in
> the GenericFunction class perhaps). But the thing is, the shared
> version was no more safe. You can't keep a reference to an Array
> because you don't know if it's shared or just wrapping data that
> will be deleted from under you. It was "shared or borrowed" rather
> than "owned or borrowed", only without the flag to tell the cases
> apart.

I'm not very happy with our current use of Array. We use std::vector
in some places and Array in other places. I don't remember what the
original intention was with Array. Is the purpose just to be able to
pass shared data as arrays back and forth to Python? Or should it be a
general array class used throughout DOLFIN C++?

If it is just for Python-wrapping, I think we should make it never own
data as Joachim suggests.

--
Anders

> -j.
>
> On 24 February 2012 19:37, Garth Wells <email address hidden> wrote:
>
> > I'm not keen on ownership flags - they were a real mess before and it's
> > been a lot better since we go rid of them.
> >
> > Would be it be possible to (1) re-use the Array so we avoid dynamic
> > allocation or (2) have an Array-like structure that always owns the data?
> > The class Array was introduced to better interface with Python, but I
> > recall that we later became aware that the Numpy interface has has a flag
> > to prevent resizing, which would make typemaps more robust.
> >
>

Revision history for this message
Garth Wells (garth-wells) wrote :
Download full text (3.3 KiB)

On 27 February 2012 13:40, Anders Logg <email address hidden> wrote:
> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
>> I'd opine that the easiest would be to make array never own the data,
>> rather than always own the data. In that way, it can wrap anything.
>>
>> * TimeSeries returns (owned) Arrays in two places. These could
>> return references to its own data (const vector<double>&), that
>> would save a copy (they are currently copied twice, once into an
>> owned Array, then again in swig into a numpy array). But maybe the
>> amount of data returned is small, in which case a vector<double>
>> will be fine.
>
> The return of arrays from TimeSeries is typically not performance
> critical so a copy is fine (which it already is).
>
>> * Can't support resize() without ownership, so everywhere resize is
>> used on a reference argument should pass a vector<double>&
>> instead. I think this is a few places only.
>>
>> At that point, Array will be a plain wrapper of others' data.
>>
>> As for your (1), it might well be possible (keep a scratch array in
>> the GenericFunction class perhaps). But the thing is, the shared
>> version was no more safe. You can't keep a reference to an Array
>> because you don't know if it's shared or just wrapping data that
>> will be deleted from under you. It was "shared or borrowed" rather
>> than "owned or borrowed", only without the flag to tell the cases
>> apart.
>
> I'm not very happy with our current use of Array. We use std::vector
> in some places and Array in other places. I don't remember what the
> original intention was with Array. Is the purpose just to be able to
> pass shared data as arrays back and forth to Python?

Yes.

> Or should it be a
> general array class used throughout DOLFIN C++?
>

No - there is no point in re-inventing std::vector. We should use
std::vector where possible. It's more flexible and can be used with
STL algorithms.

> If it is just for Python-wrapping, I think we should make it never own
> data as Joachim suggests.
>

Memory has to be created somewhere in order to be used, and it has to
be cleaned up.

There are two issues here:

1) Dynamic allocation in order to interface with UFC. Using plain
pointers rather than smart pointers is likely faster, but I think that
it's still not a solution. We should try to avoid these allocations in
loops.

2) We need to re-visit the NumPy interface. If we can create NumPy
arrays of fixed length, then we can just use std::vector, and let the
NumPy array wrap the pointer &x[0]. Maybe Johan Hake can comment on
this?

Garth

> --
> Anders
>
>
>> -j.
>>
>> On 24 February 2012 19:37, Garth Wells <email address hidden> wrote:
>>
>> > I'm not keen on ownership flags - they were a real mess before and it's
>> > been a lot better since we go rid of them.
>> >
>> > Would be it be possible to (1) re-use the Array so we avoid dynamic
>> > allocation or (2) have an Array-like structure that always owns the data?
>> > The class Array was introduced to better interface with Python, but I
>> > recall that we later became aware that the Numpy interface has has a flag
>> > to prevent resizing, which would make typemaps more robust.
>> >
>>
>
> --
> ht...

Read more...

Revision history for this message
Joachim Haga (jobh) wrote :

>> I'm not very happy with our current use of Array. We use std::vector
>> in some places and Array in other places. I don't remember what the
>> original intention was with Array. Is the purpose just to be able to
>> pass shared data as arrays back and forth to Python?
>
> Yes.

The current usage is:
- As input (Python->C++) it wraps the numpy data.
- As output (C++->Python) the data is copied into a new numpy array.

I don't know off-hand if the input case is a requirement (that C++
modifies the data) or just an optimisation.

>> Or should it be a
>> general array class used throughout DOLFIN C++?
>
> No - there is no point in re-inventing std::vector. We should use
> std::vector where possible. It's more flexible and can be used with
> STL algorithms.

I agree in general, but note that there is no way to make a
std::vector wrap numpy data like in the input case above. An Array --
even if it's just a typedef to std::pair<T*,uint> -- may be nice to
standardise how wrapped data is passed.

> 1) Dynamic allocation in order to interface with UFC. Using plain
> pointers rather than smart pointers is likely faster, but I think that
> it's still not a solution. We should try to avoid these allocations in
> loops.

There is no dynamic allocation of actual data, not before and not now.
There was, however, dynamic allocation of the shared_array reference
count which is heap allocated. That is what this merge request fixes.

-j.

Revision history for this message
Johan Hake (johan-hake) wrote :
Download full text (3.9 KiB)

On 02/27/2012 03:01 PM, Garth Wells wrote:
> On 27 February 2012 13:40, Anders Logg<email address hidden> wrote:
>> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
>>> I'd opine that the easiest would be to make array never own the data,
>>> rather than always own the data. In that way, it can wrap anything.
>>>
>>> * TimeSeries returns (owned) Arrays in two places. These could
>>> return references to its own data (const vector<double>&), that
>>> would save a copy (they are currently copied twice, once into an
>>> owned Array, then again in swig into a numpy array). But maybe the
>>> amount of data returned is small, in which case a vector<double>
>>> will be fine.
>>
>> The return of arrays from TimeSeries is typically not performance
>> critical so a copy is fine (which it already is).
>>
>>> * Can't support resize() without ownership, so everywhere resize is
>>> used on a reference argument should pass a vector<double>&
>>> instead. I think this is a few places only.
>>>
>>> At that point, Array will be a plain wrapper of others' data.
>>>
>>> As for your (1), it might well be possible (keep a scratch array in
>>> the GenericFunction class perhaps). But the thing is, the shared
>>> version was no more safe. You can't keep a reference to an Array
>>> because you don't know if it's shared or just wrapping data that
>>> will be deleted from under you. It was "shared or borrowed" rather
>>> than "owned or borrowed", only without the flag to tell the cases
>>> apart.
>>
>> I'm not very happy with our current use of Array. We use std::vector
>> in some places and Array in other places. I don't remember what the
>> original intention was with Array. Is the purpose just to be able to
>> pass shared data as arrays back and forth to Python?
>
> Yes.
>
>> Or should it be a
>> general array class used throughout DOLFIN C++?
>>
>
> No - there is no point in re-inventing std::vector. We should use
> std::vector where possible. It's more flexible and can be used with
> STL algorithms.

Agree.

>> If it is just for Python-wrapping, I think we should make it never own
>> data as Joachim suggests.

Agree. But we need to go over the interface and check that it makes
sense everywhere. TimeSeries could probably just return a std::vector
which is copied in the Python interface.

> Memory has to be created somewhere in order to be used, and it has to
> be cleaned up.
>
> There are two issues here:
>
> 1) Dynamic allocation in order to interface with UFC. Using plain
> pointers rather than smart pointers is likely faster, but I think that
> it's still not a solution. We should try to avoid these allocations in
> loops.
>
> 2) We need to re-visit the NumPy interface. If we can create NumPy
> arrays of fixed length, then we can just use std::vector, and let the
> NumPy array wrap the pointer&x[0]. Maybe Johan Hake can comment on
> this?

The problem is to pass a NumPy array to the C++ interface when it wants
a std::vector&. Then we need to copy the values. A light weight Array
class fixes that issue.

Wrapping a std::vector& into a Numpy array is possible without copying
by just passing the pointer. This would be similar to what we do today
with th...

Read more...

Revision history for this message
Anders Logg (logg) wrote :
Download full text (4.2 KiB)

On Mon, Feb 27, 2012 at 03:32:04PM -0000, Johan Hake wrote:
> On 02/27/2012 03:01 PM, Garth Wells wrote:
> > On 27 February 2012 13:40, Anders Logg<email address hidden> wrote:
> >> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
> >>> I'd opine that the easiest would be to make array never own the data,
> >>> rather than always own the data. In that way, it can wrap anything.
> >>>
> >>> * TimeSeries returns (owned) Arrays in two places. These could
> >>> return references to its own data (const vector<double>&), that
> >>> would save a copy (they are currently copied twice, once into an
> >>> owned Array, then again in swig into a numpy array). But maybe the
> >>> amount of data returned is small, in which case a vector<double>
> >>> will be fine.
> >>
> >> The return of arrays from TimeSeries is typically not performance
> >> critical so a copy is fine (which it already is).
> >>
> >>> * Can't support resize() without ownership, so everywhere resize is
> >>> used on a reference argument should pass a vector<double>&
> >>> instead. I think this is a few places only.
> >>>
> >>> At that point, Array will be a plain wrapper of others' data.
> >>>
> >>> As for your (1), it might well be possible (keep a scratch array in
> >>> the GenericFunction class perhaps). But the thing is, the shared
> >>> version was no more safe. You can't keep a reference to an Array
> >>> because you don't know if it's shared or just wrapping data that
> >>> will be deleted from under you. It was "shared or borrowed" rather
> >>> than "owned or borrowed", only without the flag to tell the cases
> >>> apart.
> >>
> >> I'm not very happy with our current use of Array. We use std::vector
> >> in some places and Array in other places. I don't remember what the
> >> original intention was with Array. Is the purpose just to be able to
> >> pass shared data as arrays back and forth to Python?
> >
> > Yes.
> >
> >> Or should it be a
> >> general array class used throughout DOLFIN C++?
> >>
> >
> > No - there is no point in re-inventing std::vector. We should use
> > std::vector where possible. It's more flexible and can be used with
> > STL algorithms.
>
> Agree.
>
> >> If it is just for Python-wrapping, I think we should make it never own
> >> data as Joachim suggests.
>
> Agree. But we need to go over the interface and check that it makes
> sense everywhere. TimeSeries could probably just return a
> std::vector which is copied in the Python interface.

Yes, definitely for TimeSeries. Perhaps we could settle for that
everytime we want to pass output data to Python?

Then Array input would essentially be limited to a few particular
callbacks that need to be made efficient (GenericFunction::eval).

--
Anders

> > Memory has to be created somewhere in order to be used, and it has
to
> > be cleaned up.
> >
> > There are two issues here:
> >
> > 1) Dynamic allocation in order to interface with UFC. Using plain
> > pointers rather than smart pointers is likely faster, but I think that
> > it's still not a solution. We should try to avoid these allocations in
> > loops.
> >
> > 2) We need to re-visit the NumPy interface. If we can create NumPy
> > arrays of fixed length,...

Read more...

Revision history for this message
Garth Wells (garth-wells) wrote :
Download full text (4.9 KiB)

On 27 February 2012 17:01, Anders Logg <email address hidden> wrote:
> On Mon, Feb 27, 2012 at 03:32:04PM -0000, Johan Hake wrote:
>> On 02/27/2012 03:01 PM, Garth Wells wrote:
>> > On 27 February 2012 13:40, Anders Logg<email address hidden>  wrote:
>> >> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
>> >>> I'd opine that the easiest would be to make array never own the data,
>> >>> rather than always own the data. In that way, it can wrap anything.
>> >>>
>> >>> * TimeSeries returns (owned) Arrays in two places. These could
>> >>> return references to its own data (const vector<double>&), that
>> >>> would save a copy (they are currently copied twice, once into an
>> >>> owned Array, then again in swig into a numpy array). But maybe the
>> >>> amount of data returned is small, in which case a vector<double>
>> >>> will be fine.
>> >>
>> >> The return of arrays from TimeSeries is typically not performance
>> >> critical so a copy is fine (which it already is).
>> >>
>> >>> * Can't support resize() without ownership, so everywhere resize is
>> >>> used on a reference argument should pass a vector<double>&
>> >>> instead. I think this is a few places only.
>> >>>
>> >>> At that point, Array will be a plain wrapper of others' data.
>> >>>
>> >>> As for your (1), it might well be possible (keep a scratch array in
>> >>> the GenericFunction class perhaps). But the thing is, the shared
>> >>> version was no more safe. You can't keep a reference to an Array
>> >>> because you don't know if it's shared or just wrapping data that
>> >>> will be deleted from under you. It was "shared or borrowed" rather
>> >>> than "owned or borrowed", only without the flag to tell the cases
>> >>> apart.
>> >>
>> >> I'm not very happy with our current use of Array. We use std::vector
>> >> in some places and Array in other places. I don't remember what the
>> >> original intention was with Array. Is the purpose just to be able to
>> >> pass shared data as arrays back and forth to Python?
>> >
>> > Yes.
>> >
>> >> Or should it be a
>> >> general array class used throughout DOLFIN C++?
>> >>
>> >
>> > No - there is no point in re-inventing std::vector. We should use
>> > std::vector where possible. It's more flexible and can be used with
>> > STL algorithms.
>>
>> Agree.
>>
>> >> If it is just for Python-wrapping, I think we should make it never own
>> >> data as Joachim suggests.
>>
>> Agree. But we need to go over the interface and check that it makes
>> sense everywhere. TimeSeries could probably just return a
>> std::vector which is copied in the Python interface.
>
> Yes, definitely for TimeSeries. Perhaps we could settle for that
> everytime we want to pass output data to Python?
>
> Then Array input would essentially be limited to a few particular
> callbacks that need to be made efficient (GenericFunction::eval).
>

In the case of GenericFunction::eval we can use std::vector if, in the
wrapping process, we can prevent resizing on the Python side.

Maybe we can remove Array and support (a) std::vectors via copy and
(b) references to a std::vector with resizing prevented.

Garth

> --
> Anders
>
>
>> > Memory has to be created somewhere in order to be used, ...

Read more...

Revision history for this message
Anders Logg (logg) wrote :
Download full text (5.3 KiB)

On Mon, Feb 27, 2012 at 07:52:27PM -0000, Garth Wells wrote:
> On 27 February 2012 17:01, Anders Logg <email address hidden> wrote:
> > On Mon, Feb 27, 2012 at 03:32:04PM -0000, Johan Hake wrote:
> >> On 02/27/2012 03:01 PM, Garth Wells wrote:
> >> > On 27 February 2012 13:40, Anders Logg<email address hidden>  wrote:
> >> >> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
> >> >>> I'd opine that the easiest would be to make array never own the data,
> >> >>> rather than always own the data. In that way, it can wrap anything.
> >> >>>
> >> >>> * TimeSeries returns (owned) Arrays in two places. These could
> >> >>> return references to its own data (const vector<double>&), that
> >> >>> would save a copy (they are currently copied twice, once into an
> >> >>> owned Array, then again in swig into a numpy array). But maybe the
> >> >>> amount of data returned is small, in which case a vector<double>
> >> >>> will be fine.
> >> >>
> >> >> The return of arrays from TimeSeries is typically not performance
> >> >> critical so a copy is fine (which it already is).
> >> >>
> >> >>> * Can't support resize() without ownership, so everywhere resize is
> >> >>> used on a reference argument should pass a vector<double>&
> >> >>> instead. I think this is a few places only.
> >> >>>
> >> >>> At that point, Array will be a plain wrapper of others' data.
> >> >>>
> >> >>> As for your (1), it might well be possible (keep a scratch array in
> >> >>> the GenericFunction class perhaps). But the thing is, the shared
> >> >>> version was no more safe. You can't keep a reference to an Array
> >> >>> because you don't know if it's shared or just wrapping data that
> >> >>> will be deleted from under you. It was "shared or borrowed" rather
> >> >>> than "owned or borrowed", only without the flag to tell the cases
> >> >>> apart.
> >> >>
> >> >> I'm not very happy with our current use of Array. We use std::vector
> >> >> in some places and Array in other places. I don't remember what the
> >> >> original intention was with Array. Is the purpose just to be able to
> >> >> pass shared data as arrays back and forth to Python?
> >> >
> >> > Yes.
> >> >
> >> >> Or should it be a
> >> >> general array class used throughout DOLFIN C++?
> >> >>
> >> >
> >> > No - there is no point in re-inventing std::vector. We should use
> >> > std::vector where possible. It's more flexible and can be used with
> >> > STL algorithms.
> >>
> >> Agree.
> >>
> >> >> If it is just for Python-wrapping, I think we should make it never own
> >> >> data as Joachim suggests.
> >>
> >> Agree. But we need to go over the interface and check that it makes
> >> sense everywhere. TimeSeries could probably just return a
> >> std::vector which is copied in the Python interface.
> >
> > Yes, definitely for TimeSeries. Perhaps we could settle for that
> > everytime we want to pass output data to Python?
> >
> > Then Array input would essentially be limited to a few particular
> > callbacks that need to be made efficient (GenericFunction::eval).
> >
>
> In the case of GenericFunction::eval we can use std::vector if, in
> the wrapping process, we can prevent resizing on the Python side.

Don't know if that's po...

Read more...

Revision history for this message
Johan Hake (johan-hake) wrote :
Download full text (6.7 KiB)

On 02/27/2012 09:16 PM, Anders Logg wrote:
> On Mon, Feb 27, 2012 at 07:52:27PM -0000, Garth Wells wrote:
>> On 27 February 2012 17:01, Anders Logg<email address hidden> wrote:
>>> On Mon, Feb 27, 2012 at 03:32:04PM -0000, Johan Hake wrote:
>>>> On 02/27/2012 03:01 PM, Garth Wells wrote:
>>>>> On 27 February 2012 13:40, Anders Logg<email address hidden> wrote:
>>>>>> On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
>>>>>>> I'd opine that the easiest would be to make array never own the data,
>>>>>>> rather than always own the data. In that way, it can wrap anything.
>>>>>>>
>>>>>>> * TimeSeries returns (owned) Arrays in two places. These could
>>>>>>> return references to its own data (const vector<double>&), that
>>>>>>> would save a copy (they are currently copied twice, once into an
>>>>>>> owned Array, then again in swig into a numpy array). But maybe the
>>>>>>> amount of data returned is small, in which case a vector<double>
>>>>>>> will be fine.
>>>>>>
>>>>>> The return of arrays from TimeSeries is typically not performance
>>>>>> critical so a copy is fine (which it already is).
>>>>>>
>>>>>>> * Can't support resize() without ownership, so everywhere resize is
>>>>>>> used on a reference argument should pass a vector<double>&
>>>>>>> instead. I think this is a few places only.
>>>>>>>
>>>>>>> At that point, Array will be a plain wrapper of others' data.
>>>>>>>
>>>>>>> As for your (1), it might well be possible (keep a scratch array in
>>>>>>> the GenericFunction class perhaps). But the thing is, the shared
>>>>>>> version was no more safe. You can't keep a reference to an Array
>>>>>>> because you don't know if it's shared or just wrapping data that
>>>>>>> will be deleted from under you. It was "shared or borrowed" rather
>>>>>>> than "owned or borrowed", only without the flag to tell the cases
>>>>>>> apart.
>>>>>>
>>>>>> I'm not very happy with our current use of Array. We use std::vector
>>>>>> in some places and Array in other places. I don't remember what the
>>>>>> original intention was with Array. Is the purpose just to be able to
>>>>>> pass shared data as arrays back and forth to Python?
>>>>>
>>>>> Yes.
>>>>>
>>>>>> Or should it be a
>>>>>> general array class used throughout DOLFIN C++?
>>>>>>
>>>>>
>>>>> No - there is no point in re-inventing std::vector. We should use
>>>>> std::vector where possible. It's more flexible and can be used with
>>>>> STL algorithms.
>>>>
>>>> Agree.
>>>>
>>>>>> If it is just for Python-wrapping, I think we should make it never own
>>>>>> data as Joachim suggests.
>>>>
>>>> Agree. But we need to go over the interface and check that it makes
>>>> sense everywhere. TimeSeries could probably just return a
>>>> std::vector which is copied in the Python interface.
>>>
>>> Yes, definitely for TimeSeries. Perhaps we could settle for that
>>> everytime we want to pass output data to Python?
>>>
>>> Then Array input would essentially be limited to a few particular
>>> callbacks that need to be made efficient (GenericFunction::eval).
>>>
>>
>> In the case of GenericFunction::eval we can use std::vector if, in
>> the wrapping process, we can prevent resizing on the Python side.
>
> Don't know if ...

Read more...

Revision history for this message
Anders Logg (logg) wrote :
Download full text (5.4 KiB)

On Tue, Feb 28, 2012 at 05:08:11AM +0100, Johan Hake wrote:
> On 02/27/2012 09:16 PM, Anders Logg wrote:
> >On Mon, Feb 27, 2012 at 07:52:27PM -0000, Garth Wells wrote:
> >>On 27 February 2012 17:01, Anders Logg<email address hidden> wrote:
> >>>On Mon, Feb 27, 2012 at 03:32:04PM -0000, Johan Hake wrote:
> >>>>On 02/27/2012 03:01 PM, Garth Wells wrote:
> >>>>>On 27 February 2012 13:40, Anders Logg<email address hidden> wrote:
> >>>>>>On Fri, Feb 24, 2012 at 07:01:57PM -0000, Joachim Haga wrote:
> >>>>>>>I'd opine that the easiest would be to make array never own the data,
> >>>>>>>rather than always own the data. In that way, it can wrap anything.
> >>>>>>>
> >>>>>>>* TimeSeries returns (owned) Arrays in two places. These could
> >>>>>>>return references to its own data (const vector<double>&), that
> >>>>>>>would save a copy (they are currently copied twice, once into an
> >>>>>>>owned Array, then again in swig into a numpy array). But maybe the
> >>>>>>>amount of data returned is small, in which case a vector<double>
> >>>>>>>will be fine.
> >>>>>>
> >>>>>>The return of arrays from TimeSeries is typically not performance
> >>>>>>critical so a copy is fine (which it already is).
> >>>>>>
> >>>>>>>* Can't support resize() without ownership, so everywhere resize is
> >>>>>>>used on a reference argument should pass a vector<double>&
> >>>>>>>instead. I think this is a few places only.
> >>>>>>>
> >>>>>>>At that point, Array will be a plain wrapper of others' data.
> >>>>>>>
> >>>>>>>As for your (1), it might well be possible (keep a scratch array in
> >>>>>>>the GenericFunction class perhaps). But the thing is, the shared
> >>>>>>>version was no more safe. You can't keep a reference to an Array
> >>>>>>>because you don't know if it's shared or just wrapping data that
> >>>>>>>will be deleted from under you. It was "shared or borrowed" rather
> >>>>>>>than "owned or borrowed", only without the flag to tell the cases
> >>>>>>>apart.
> >>>>>>
> >>>>>>I'm not very happy with our current use of Array. We use std::vector
> >>>>>>in some places and Array in other places. I don't remember what the
> >>>>>>original intention was with Array. Is the purpose just to be able to
> >>>>>>pass shared data as arrays back and forth to Python?
> >>>>>
> >>>>>Yes.
> >>>>>
> >>>>>>Or should it be a
> >>>>>>general array class used throughout DOLFIN C++?
> >>>>>>
> >>>>>
> >>>>>No - there is no point in re-inventing std::vector. We should use
> >>>>>std::vector where possible. It's more flexible and can be used with
> >>>>>STL algorithms.
> >>>>
> >>>>Agree.
> >>>>
> >>>>>>If it is just for Python-wrapping, I think we should make it never own
> >>>>>>data as Joachim suggests.
> >>>>
> >>>>Agree. But we need to go over the interface and check that it makes
> >>>>sense everywhere. TimeSeries could probably just return a
> >>>>std::vector which is copied in the Python interface.
> >>>
> >>>Yes, definitely for TimeSeries. Perhaps we could settle for that
> >>>everytime we want to pass output data to Python?
> >>>
> >>>Then Array input would essentially be limited to a few particular
> >>>callbacks that need to be made efficient (GenericFunction::eval).
> >>>
> >>
> >>In the cas...

Read more...

lp:~jobh/dolfin/fast-array updated
6593. By Joachim Haga

Fix missing return statement

6594. By Joachim Haga

Merge with trunk

6595. By Joachim Haga

Change TimeSeries interface to return std::vector rather than Array

Revision history for this message
Joachim Haga (jobh) wrote :

This seems to have stalled without a consensus. Still, I think the improvements are too dramatic to just drop. Assembling a "v*f*dx" RHS on a 64^3 cube (twice):

6.95 s before
2.30 s after

With Garth's suggestion of reusing an Array: 2.54s, but not thread safe without some extra complexity (likely compiler-dependent).

I'd like to repeat my argument that my proposed change isn't any less safe than what's there already. The old Array used reference_to_no_delete_ptr in several constructors, thus the memory was managed by the caller -- exactly the same as it is here, if the Array is not the owner. Arrays were never shared [*], so the "shared" variant is exactly the same as the new "owned" variant.

Note [*]: It was used implicitly to transfer ownership in the TimeSeries return values. Since there's agreement than an extra copy does no harm there, I've changed those to return std::vector instead.

Then it can be deprecated or redesigned or whatever later, but in the meantime dolfin will be much faster :)

PS. The "interface version" thing seems to not work for all instant files, so instant-clean is still required. How should this be handled?

Revision history for this message
Johan Hake (johan-hake) wrote :

I am in favor of applying the patch.

On Tue, Mar 6, 2012 at 12:20 PM, Joachim Haga <email address hidden> wrote:
> This seems to have stalled without a consensus. Still, I think the improvements are too dramatic to just drop. Assembling a "v*f*dx" RHS on a 64^3 cube (twice):
>
> 6.95 s before
> 2.30 s after
>
> With Garth's suggestion of reusing an Array: 2.54s, but not thread safe without some extra complexity (likely compiler-dependent).
>
> I'd like to repeat my argument that my proposed change isn't any less safe than what's there already. The old Array used reference_to_no_delete_ptr in several constructors, thus the memory was managed by the caller -- exactly the same as it is here, if the Array is not the owner. Arrays were never shared [*], so the "shared" variant is exactly the same as the new "owned" variant.
>
> Note [*]: It was used implicitly to transfer ownership in the TimeSeries return values. Since there's agreement than an extra copy does no harm there, I've changed those to return std::vector instead.
>
> Then it can be deprecated or redesigned or whatever later, but in the meantime dolfin will be much faster :)
>
> PS. The "interface version" thing seems to not work for all instant files, so instant-clean is still required. How should this be handled?

Not sure what is not working, but it should be enough to change the
DOLFIN_VERSION_MICRO, as this is eventualy included in the md5sum
which determines if a modules should be recompiled or not.

Johan

> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> Your team DOLFIN Core Team is requested to review the proposed merge of lp:~jobh/dolfin/fast-array into lp:dolfin.

Revision history for this message
Anders Logg (logg) wrote :

I'm also very much in favor.

--
Anders

On Tue, Mar 06, 2012 at 11:53:31AM -0000, Johan Hake wrote:
> I am in favor of applying the patch.
>
> On Tue, Mar 6, 2012 at 12:20 PM, Joachim Haga <email address hidden> wrote:
> > This seems to have stalled without a consensus. Still, I think the improvements are too dramatic to just drop. Assembling a "v*f*dx" RHS on a 64^3 cube (twice):
> >
> > 6.95 s before
> > 2.30 s after
> >
> > With Garth's suggestion of reusing an Array: 2.54s, but not thread safe without some extra complexity (likely compiler-dependent).
> >
> > I'd like to repeat my argument that my proposed change isn't any less safe than what's there already. The old Array used reference_to_no_delete_ptr in several constructors, thus the memory was managed by the caller -- exactly the same as it is here, if the Array is not the owner. Arrays were never shared [*], so the "shared" variant is exactly the same as the new "owned" variant.
> >
> > Note [*]: It was used implicitly to transfer ownership in the TimeSeries return values. Since there's agreement than an extra copy does no harm there, I've changed those to return std::vector instead.
> >
> > Then it can be deprecated or redesigned or whatever later, but in the meantime dolfin will be much faster :)
> >
> > PS. The "interface version" thing seems to not work for all instant files, so instant-clean is still required. How should this be handled?
>
> Not sure what is not working, but it should be enough to change the
> DOLFIN_VERSION_MICRO, as this is eventualy included in the md5sum
> which determines if a modules should be recompiled or not.
>
> Johan
>
>

Revision history for this message
Garth Wells (garth-wells) wrote :

On 6 March 2012 12:11, Anders Logg <email address hidden> wrote:
> I'm also very much in favor.
>

I'm happy in principle, but want some clarity on Array. Can we make it
that Array is always a view (i.e., never owns that data), and
therefore cannot be resized? This would clean up some const hacks.

Garth

> --
> Anders
>
> On Tue, Mar 06, 2012 at 11:53:31AM -0000, Johan Hake wrote:
>> I am in favor of applying the patch.
>>
>> On Tue, Mar 6, 2012 at 12:20 PM, Joachim Haga <email address hidden> wrote:
>> > This seems to have stalled without a consensus. Still, I think the improvements are too dramatic to just drop. Assembling a "v*f*dx" RHS on a 64^3 cube (twice):
>> >
>> > 6.95 s before
>> > 2.30 s after
>> >
>> > With Garth's suggestion of reusing an Array: 2.54s, but not thread safe without some extra complexity (likely compiler-dependent).
>> >
>> > I'd like to repeat my argument that my proposed change isn't any less safe than what's there already. The old Array used reference_to_no_delete_ptr in several constructors, thus the memory was managed by the caller -- exactly the same as it is here, if the Array is not the owner. Arrays were never shared [*], so the "shared" variant is exactly the same as the new "owned" variant.
>> >
>> > Note [*]: It was used implicitly to transfer ownership in the TimeSeries return values. Since there's agreement than an extra copy does no harm there, I've changed those to return std::vector instead.
>> >
>> > Then it can be deprecated or redesigned or whatever later, but in the meantime dolfin will be much faster :)
>> >
>> > PS. The "interface version" thing seems to not work for all instant files, so instant-clean is still required. How should this be handled?
>>
>> Not sure what is not working, but it should be enough to change the
>> DOLFIN_VERSION_MICRO, as this is eventualy included in the md5sum
>> which determines if a modules should be recompiled or not.
>>
>> Johan
>>
>>
>
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> Your team DOLFIN Core Team is requested to review the proposed merge of lp:~jobh/dolfin/fast-array into lp:dolfin.

Revision history for this message
Anders Logg (logg) wrote :

On Tue, Mar 06, 2012 at 12:28:20PM -0000, Garth Wells wrote:
> On 6 March 2012 12:11, Anders Logg <email address hidden> wrote:
> > I'm also very much in favor.
> >
>
> I'm happy in principle, but want some clarity on Array. Can we make it
> that Array is always a view (i.e., never owns that data), and
> therefore cannot be resized? This would clean up some const hacks.

That's fine with me. And in addition we should limit the use of Array
to just the few places where we need it for passing data through
the SWIG layer without copying.

--
Anders

> Garth
>
> >
> > On Tue, Mar 06, 2012 at 11:53:31AM -0000, Johan Hake wrote:
> >> I am in favor of applying the patch.
> >>
> >> On Tue, Mar 6, 2012 at 12:20 PM, Joachim Haga <email address hidden> wrote:
> >> > This seems to have stalled without a consensus. Still, I think the improvements are too dramatic to just drop. Assembling a "v*f*dx" RHS on a 64^3 cube (twice):
> >> >
> >> > 6.95 s before
> >> > 2.30 s after
> >> >
> >> > With Garth's suggestion of reusing an Array: 2.54s, but not thread safe without some extra complexity (likely compiler-dependent).
> >> >
> >> > I'd like to repeat my argument that my proposed change isn't any less safe than what's there already. The old Array used reference_to_no_delete_ptr in several constructors, thus the memory was managed by the caller -- exactly the same as it is here, if the Array is not the owner. Arrays were never shared [*], so the "shared" variant is exactly the same as the new "owned" variant.
> >> >
> >> > Note [*]: It was used implicitly to transfer ownership in the TimeSeries return values. Since there's agreement than an extra copy does no harm there, I've changed those to return std::vector instead.
> >> >
> >> > Then it can be deprecated or redesigned or whatever later, but in the meantime dolfin will be much faster :)
> >> >
> >> > PS. The "interface version" thing seems to not work for all instant files, so instant-clean is still required. How should this be handled?
> >>
> >> Not sure what is not working, but it should be enough to change the
> >> DOLFIN_VERSION_MICRO, as this is eventualy included in the md5sum
> >> which determines if a modules should be recompiled or not.
> >>
> >> Johan
> >>
> >>
> >
>

Revision history for this message
Johan Hake (johan-hake) wrote :

On Tue, Mar 6, 2012 at 1:28 PM, Garth Wells <email address hidden> wrote:
> On 6 March 2012 12:11, Anders Logg <email address hidden> wrote:
>> I'm also very much in favor.
>>
>
> I'm happy in principle, but want some clarity on Array. Can we make it
> that Array is always a view (i.e., never owns that data), and
> therefore cannot be resized? This would clean up some const hacks.

I agree. For all argments needing to be resized should use
std::vector. Not sure where the resize functionality is/was used.

Johan

Revision history for this message
Joachim Haga (jobh) wrote :

>
> > I'm happy in principle, but want some clarity on Array. Can we make it
> > that Array is always a view (i.e., never owns that data), and
> > therefore cannot be resized? This would clean up some const hacks.
>
> I agree. For all argments needing to be resized should use
> std::vector. Not sure where the resize functionality is/was used.

It is possible (of course). There are quite a few user-exposed interfaces
that need changing (f.x. all the GeneralVector::set/get methods, since it
would be strange to just change the get methods).

And it may be a lot of grunt work. But I'll have a go at it if you say
that's the way to go (even if it requires change to user code).

-j.

Revision history for this message
Joachim Haga (jobh) wrote :

After looking at la_get_set_items.i: _get_vector_values(), shown below, I
think I'll punt on this. It's just too much work for an uncertain outcome
(it is quite possible that a lot of complexity has to be added back to deal
with cases like this, making this pointless).

// Returns the values from a Vector.
dolfin::Array<double>& _get_vector_values( dolfin::GenericVector* self)
{
  dolfin::Array<double>* values;
  try
  {
    // Try accessing the value pointer directly [jobh: return borrowed data]
    double* data_values = self->data();
    values = new dolfin::Array<double>(self->size(), data_values);
  }
  catch (std::runtime_error e)
  {
    // We couldn't access the values directly [jobh: return owned data]
    values = new dolfin::Array<double>(self->size());
    self->get_local(*values);
  }
  return *values;
}

On 6 March 2012 15:01, Joachim Berdal Haga <email address hidden> wrote:

> > I'm happy in principle, but want some clarity on Array. Can we make it
>> > that Array is always a view (i.e., never owns that data), and
>> > therefore cannot be resized? This would clean up some const hacks.
>>
>> I agree. For all argments needing to be resized should use
>> std::vector. Not sure where the resize functionality is/was used.
>
>
> It is possible (of course). There are quite a few user-exposed interfaces
> that need changing (f.x. all the GeneralVector::set/get methods, since it
> would be strange to just change the get methods).
>
> And it may be a lot of grunt work. But I'll have a go at it if you say
> that's the way to go (even if it requires change to user code).
>
> -j.
>
>

Revision history for this message
Garth Wells (garth-wells) wrote :

On 6 March 2012 15:13, Joachim Haga <email address hidden> wrote:
> After looking at la_get_set_items.i: _get_vector_values(), shown below, I
> think I'll punt on this. It's just too much work for an uncertain outcome
> (it is quite possible that a lot of complexity has to be added back to deal
> with cases like this, making this pointless).
>
> // Returns the values from a Vector.
> dolfin::Array<double>& _get_vector_values( dolfin::GenericVector* self)
> {
>  dolfin::Array<double>* values;
>  try
>  {
>    // Try accessing the value pointer directly [jobh: return borrowed data]
>    double* data_values = self->data();
>    values = new dolfin::Array<double>(self->size(), data_values);
>  }
>  catch (std::runtime_error e)
>  {
>    // We couldn't access the values directly [jobh: return owned data]
>    values = new dolfin::Array<double>(self->size());
>    self->get_local(*values);
>  }
>  return *values;
> }
>

We should just be able to use std::vector in the C++ interface for this.

Garth

>
> On 6 March 2012 15:01, Joachim Berdal Haga <email address hidden> wrote:
>
>> > I'm happy in principle, but want some clarity on Array. Can we make it
>>> > that Array is always a view (i.e., never owns that data), and
>>> > therefore cannot be resized? This would clean up some const hacks.
>>>
>>> I agree. For all argments needing to be resized should use
>>> std::vector. Not sure where the resize functionality is/was used.
>>
>>
>> It is possible (of course). There are quite a few user-exposed interfaces
>> that need changing (f.x. all the GeneralVector::set/get methods, since it
>> would be strange to just change the get methods).
>>
>> And it may be a lot of grunt work. But I'll have a go at it if you say
>> that's the way to go (even if it requires change to user code).
>>
>> -j.
>>
>>
>
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> Your team DOLFIN Core Team is requested to review the proposed merge of lp:~jobh/dolfin/fast-array into lp:dolfin.

Revision history for this message
Anders Logg (logg) wrote :

On Tue, Mar 06, 2012 at 02:10:28PM -0000, Joachim Haga wrote:
> >
> > > I'm happy in principle, but want some clarity on Array. Can we make it
> > > that Array is always a view (i.e., never owns that data), and
> > > therefore cannot be resized? This would clean up some const hacks.
> >
> > I agree. For all argments needing to be resized should use
> > std::vector. Not sure where the resize functionality is/was used.
>
>
> It is possible (of course). There are quite a few user-exposed interfaces
> that need changing (f.x. all the GeneralVector::set/get methods, since it
> would be strange to just change the get methods).
>
> And it may be a lot of grunt work. But I'll have a go at it if you say
> that's the way to go (even if it requires change to user code).

I suggest we merge this now, and think about cleaning up the use of
Array later.

Just to check: do we break any user interfaces with this patch? I
assume not.

--
Anders

Revision history for this message
Johan Hake (johan-hake) wrote :

On Tue, Mar 6, 2012 at 3:10 PM, Joachim Haga <email address hidden> wrote:
>>
>> > I'm happy in principle, but want some clarity on Array. Can we make it
>> > that Array is always a view (i.e., never owns that data), and
>> > therefore cannot be resized? This would clean up some const hacks.
>>
>> I agree. For all argments needing to be resized should use
>> std::vector. Not sure where the resize functionality is/was used.
>
> It is possible (of course). There are quite a few user-exposed interfaces
> that need changing (f.x. all the GeneralVector::set/get methods, since it
> would be strange to just change the get methods).

I did not anticipate using std::vector for these methods as these
methods assume the user provides arrays with the correct size. It
would cost too much to resize std::vector for these operations. Maybe
we can use Array<double> for these but for now they just work with
NumPy arrays directly.

Johan

> And it may be a lot of grunt work. But I'll have a go at it if you say
> that's the way to go (even if it requires change to user code).

> -j.
>
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> Your team DOLFIN Core Team is requested to review the proposed merge of lp:~jobh/dolfin/fast-array into lp:dolfin.

Revision history for this message
Johan Hake (johan-hake) wrote :

On Tue, Mar 6, 2012 at 8:19 PM, Anders Logg <email address hidden> wrote:
> On Tue, Mar 06, 2012 at 02:10:28PM -0000, Joachim Haga wrote:
>> >
>> > > I'm happy in principle, but want some clarity on Array. Can we make it
>> > > that Array is always a view (i.e., never owns that data), and
>> > > therefore cannot be resized? This would clean up some const hacks.
>> >
>> > I agree. For all argments needing to be resized should use
>> > std::vector. Not sure where the resize functionality is/was used.
>>
>>
>> It is possible (of course). There are quite a few user-exposed interfaces
>> that need changing (f.x. all the GeneralVector::set/get methods, since it
>> would be strange to just change the get methods).
>>
>> And it may be a lot of grunt work. But I'll have a go at it if you say
>> that's the way to go (even if it requires change to user code).
>
> I suggest we merge this now, and think about cleaning up the use of
> Array later.

I agree. I do not have a working DOLFIN right now so I will
unfortunately not be able to do it.

Johan

> Just to check: do we break any user interfaces with this patch? I
> assume not.
>
> --
> Anders
>
> --
> https://code.launchpad.net/~jobh/dolfin/fast-array/+merge/94467
> Your team DOLFIN Core Team is requested to review the proposed merge of lp:~jobh/dolfin/fast-array into lp:dolfin.

Revision history for this message
Anders Logg (logg) wrote :

On Tue, Mar 06, 2012 at 08:16:47PM -0000, Johan Hake wrote:
> On Tue, Mar 6, 2012 at 8:19 PM, Anders Logg <email address hidden> wrote:
> > On Tue, Mar 06, 2012 at 02:10:28PM -0000, Joachim Haga wrote:
> >> >
> >> > > I'm happy in principle, but want some clarity on Array. Can we make it
> >> > > that Array is always a view (i.e., never owns that data), and
> >> > > therefore cannot be resized? This would clean up some const hacks.
> >> >
> >> > I agree. For all argments needing to be resized should use
> >> > std::vector. Not sure where the resize functionality is/was used.
> >>
> >>
> >> It is possible (of course). There are quite a few user-exposed interfaces
> >> that need changing (f.x. all the GeneralVector::set/get methods, since it
> >> would be strange to just change the get methods).
> >>
> >> And it may be a lot of grunt work. But I'll have a go at it if you say
> >> that's the way to go (even if it requires change to user code).
> >
> > I suggest we merge this now, and think about cleaning up the use of
> > Array later.
>
> I agree. I do not have a working DOLFIN right now so I will
> unfortunately not be able to do it.

I can merge if there are no objections.

--
Anders

> Johan
>
> > Just to check: do we break any user interfaces with this patch? I
> > assume not.
> >
> >
>

Revision history for this message
Joachim Haga (jobh) wrote :

>
> >> I agree. For all argments needing to be resized should use
> >> std::vector. Not sure where the resize functionality is/was used.
> >
> > It is possible (of course). There are quite a few user-exposed interfaces
> > that need changing (f.x. all the GeneralVector::set/get methods, since it
> > would be strange to just change the get methods).
>
> I did not anticipate using std::vector for these methods as these
> methods assume the user provides arrays with the correct size. It
> would cost too much to resize std::vector for these operations. Maybe
>

Not sure if we're talking about the same thing? PETScVector::get_local for
example uses resize() on the Array& that is passed as parameter.

Revision history for this message
Joachim Haga (jobh) wrote :

On 6 March 2012 21:31, Anders Logg <email address hidden> wrote:

> > > I suggest we merge this now, and think about cleaning up the use of
> > > Array later.
> >
> > I agree. I do not have a working DOLFIN right now so I will
> > unfortunately not be able to do it.
>
> I can merge if there are no objections.
>

Certainly not from me! But hold on a bit, tomorrow morning I will check the
instant issue, and see if it's possible to disable the copy constructor (to
ensure it's not used in unanticipated ways).

-j.

Revision history for this message
Johan Hake (johan-hake) wrote :

On Tue, Mar 6, 2012 at 10:04 PM, Joachim Haga <email address hidden> wrote:
>>
>> >> I agree. For all argments needing to be resized should use
>> >> std::vector. Not sure where the resize functionality is/was used.
>> >
>> > It is possible (of course). There are quite a few user-exposed interfaces
>> > that need changing (f.x. all the GeneralVector::set/get methods, since it
>> > would be strange to just change the get methods).
>>
>> I did not anticipate using std::vector for these methods as these
>> methods assume the user provides arrays with the correct size. It
>> would cost too much to resize std::vector for these operations. Maybe
>>
>
> Not sure if we're talking about the same thing? PETScVector::get_local for
> example uses resize() on the Array& that is passed as parameter.

You are right. We do not talk about the same thing.

Here I think we should just check that the user pass an Array of the
correct size avoiding resizing.

Johan

Revision history for this message
Joachim Haga (jobh) wrote :

On 6 March 2012 17:55, Garth Wells <email address hidden> wrote:

> On 6 March 2012 15:13, Joachim Haga <email address hidden> wrote:
> > After looking at la_get_set_items.i: _get_vector_values(), shown below, I
> > think I'll punt on this. It's just too much work for an uncertain outcome
> > (it is quite possible that a lot of complexity has to be added back to
> deal
> > with cases like this, making this pointless).
> >
> > // Returns the values from a Vector.
> > dolfin::Array<double>& _get_vector_values( dolfin::GenericVector* self)
>
> We should just be able to use std::vector in the C++ interface for this.
>

Hm, yes, I guess an extra copy won't matter that much here. I'll see how it
goes.

-j.

Revision history for this message
Johan Hake (johan-hake) wrote :

On Tue, Mar 6, 2012 at 10:50 PM, Joachim Haga <email address hidden> wrote:
> On 6 March 2012 17:55, Garth Wells <email address hidden> wrote:
>
>> On 6 March 2012 15:13, Joachim Haga <email address hidden> wrote:
>> > After looking at la_get_set_items.i: _get_vector_values(), shown below, I
>> > think I'll punt on this. It's just too much work for an uncertain outcome
>> > (it is quite possible that a lot of complexity has to be added back to
>> deal
>> > with cases like this, making this pointless).
>> >
>> > // Returns the values from a Vector.
>> > dolfin::Array<double>& _get_vector_values( dolfin::GenericVector* self)
>>
>> We should just be able to use std::vector in the C++ interface for this.
>>
>
> Hm, yes, I guess an extra copy won't matter that much here. I'll see how it
> goes.

We can change this syntax to:

  void _get_vector_values(dolfin::GenericVector* self,
dolfin::Array<double>& values)

where values now is just a view of a numpy array. In the Python layer
we then create the NumPy array of correct size, call the function and
populate the values.

Johan

lp:~jobh/dolfin/fast-array updated
6596. By Joachim Haga

Disable Array copy constructor, remove utility methods that are not used

6597. By Joachim Haga

Merge with trunk

Revision history for this message
Joachim Haga (jobh) wrote :

I've now pushed a version which is merged with trunk (the merge wasn't clean so I thought it wise) and has been fully tested. The recent changes are:

- Disable the Array copy constructor, to make it safer (no unanticipated sharing or copying).
- Allow resize() to same size even for un-owned Arrays, it turned out that the ale code used this.
- Remove unused utility methods (Array::zero, Array::min, etc)

It passes all tests after merge. (KrylovSolver and one CGAL demo fail, but that's not new.)

Johan: The interface version I mentioned is something I added to compilemodules.py which changes the hash without changing the visible version. If you think it better to change DOLFIN_VERSION_MICRO, I'll do that instead (but if so, what comes after "+"?)

Revision history for this message
Anders Logg (logg) wrote :

I'll merge this later if there are now objections.

--
Anders

On Wed, Mar 07, 2012 at 01:28:34PM -0000, Joachim Haga wrote:
> I've now pushed a version which is merged with trunk (the merge wasn't clean so I thought it wise) and has been fully tested. The recent changes are:
>
> - Disable the Array copy constructor, to make it safer (no unanticipated sharing or copying).
> - Allow resize() to same size even for un-owned Arrays, it turned out that the ale code used this.
> - Remove unused utility methods (Array::zero, Array::min, etc)
>
> It passes all tests after merge. (KrylovSolver and one CGAL demo fail, but that's not new.)
>
> Johan: The interface version I mentioned is something I added to compilemodules.py which changes the hash without changing the visible version. If you think it better to change DOLFIN_VERSION_MICRO, I'll do that instead (but if so, what comes after "+"?)

Revision history for this message
Anders Logg (logg) wrote :

Merged.

Joachim, could you send a patch for ChangeLog to include one-line
summaries of all your changes. Thanks.

--
Anders

On Wed, Mar 07, 2012 at 01:28:34PM -0000, Joachim Haga wrote:
> I've now pushed a version which is merged with trunk (the merge wasn't clean so I thought it wise) and has been fully tested. The recent changes are:
>
> - Disable the Array copy constructor, to make it safer (no unanticipated sharing or copying).
> - Allow resize() to same size even for un-owned Arrays, it turned out that the ale code used this.
> - Remove unused utility methods (Array::zero, Array::min, etc)
>
> It passes all tests after merge. (KrylovSolver and one CGAL demo fail, but that's not new.)
>
> Johan: The interface version I mentioned is something I added to compilemodules.py which changes the hash without changing the visible version. If you think it better to change DOLFIN_VERSION_MICRO, I'll do that instead (but if so, what comes after "+"?)

Revision history for this message
Joachim Haga (jobh) wrote :

=== modified file 'ChangeLog'
--- ChangeLog 2012-02-13 21:49:10 +0000
+++ ChangeLog 2012-03-08 12:12:20 +0000
@@ -1,3 +1,8 @@
+ - MPI functionality for distributing values between neighbours
+ - SystemAssembler now works in parallel with topological/geometric
boundary search
+ - New symmetric assembler with ability for stand-alone RHS assemble
+ - Major speed-up of DirichletBC computation and mesh marking
+ - Major speed-up of assembly of functions and expressions
  - Major speed-up of mesh topology computation

On 8 March 2012 11:46, Anders Logg <email address hidden> wrote:
> Merged.
>
> Joachim, could you send a patch for ChangeLog to include one-line
> summaries of all your changes. Thanks.
>
> --
> Anders
>
>
> On Wed, Mar 07, 2012 at 01:28:34PM -0000, Joachim Haga wrote:
>> I've now pushed a version which is merged with trunk (the merge wasn't clean so I thought it wise) and has been fully tested. The recent changes are:
>>
>> - Disable the Array copy constructor, to make it safer (no unanticipated sharing or copying).
>> - Allow resize() to same size even for un-owned Arrays, it turned out that the ale code used this.
>> - Remove unused utility methods (Array::zero, Array::min, etc)
>>
>> It passes all tests after merge. (KrylovSolver and one CGAL demo fail, but that's not new.)
>>
>> Johan: The interface version I mentioned is something I added to compilemodules.py which changes the hash without changing the visible version. If you think it better to change DOLFIN_VERSION_MICRO, I'll do that instead (but if so, what comes after "+"?)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dolfin/adaptivity/TimeSeries.cpp'
2--- dolfin/adaptivity/TimeSeries.cpp 2012-03-01 12:01:06 +0000
3+++ dolfin/adaptivity/TimeSeries.cpp 2012-03-07 13:15:44 +0000
4@@ -23,6 +23,7 @@
5 #include <sstream>
6 #include <boost/scoped_ptr.hpp>
7
8+#include <dolfin/common/constants.h>
9 #include <dolfin/io/File.h>
10 #include <dolfin/io/BinaryFile.h>
11 #include <dolfin/la/GenericVector.h>
12@@ -207,20 +208,14 @@
13 file >> mesh;
14 }
15 //-----------------------------------------------------------------------------
16-Array<double> TimeSeries::vector_times() const
17+std::vector<double> TimeSeries::vector_times() const
18 {
19- Array<double> times(_vector_times.size());
20- for (uint i = 0; i < _vector_times.size(); i++)
21- times[i] = _vector_times[i];
22- return times;
23+ return _vector_times;
24 }
25 //-----------------------------------------------------------------------------
26-Array<double> TimeSeries::mesh_times() const
27+std::vector<double> TimeSeries::mesh_times() const
28 {
29- Array<double> times(_mesh_times.size());
30- for (uint i = 0; i < _mesh_times.size(); i++)
31- times[i] = _mesh_times[i];
32- return times;
33+ return _mesh_times;
34 }
35 //-----------------------------------------------------------------------------
36 void TimeSeries::clear()
37
38=== modified file 'dolfin/adaptivity/TimeSeries.h'
39--- dolfin/adaptivity/TimeSeries.h 2011-10-24 04:11:41 +0000
40+++ dolfin/adaptivity/TimeSeries.h 2012-03-07 13:15:44 +0000
41@@ -22,7 +22,7 @@
42 #define __TIME_SERIES_H
43
44 #include <string>
45-#include <dolfin/common/Array.h>
46+#include <vector>
47 #include <dolfin/common/Variable.h>
48
49 namespace dolfin
50@@ -104,16 +104,16 @@
51 /// Return array of sample times for vectors
52 ///
53 /// *Returns*
54- /// _Array_ <double>
55+ /// std::vector<double>
56 /// The times.
57- Array<double> vector_times() const;
58+ std::vector<double> vector_times() const;
59
60 /// Return array of sample times for meshes
61 ///
62 /// *Returns*
63- /// _Array_ <double>
64+ /// std::vector<double>
65 /// The times.
66- Array<double> mesh_times() const;
67+ std::vector<double> mesh_times() const;
68
69 /// Clear time series
70 void clear();
71
72=== modified file 'dolfin/ale/HarmonicSmoothing.cpp'
73--- dolfin/ale/HarmonicSmoothing.cpp 2012-02-01 07:31:55 +0000
74+++ dolfin/ale/HarmonicSmoothing.cpp 2012-03-07 13:15:44 +0000
75@@ -108,7 +108,7 @@
76 solve(A, x, b, "gmres", prec);
77
78 // Get new coordinates
79- Array<double> _new_coordinates(N, new_coordinates.data().get() + dim*N);
80+ Array<double> _new_coordinates(N, new_coordinates.data() + dim*N);
81 x.get_local(_new_coordinates);
82 }
83
84
85=== modified file 'dolfin/common/Array.h'
86--- dolfin/common/Array.h 2012-03-01 12:01:06 +0000
87+++ dolfin/common/Array.h 2012-03-07 13:15:44 +0000
88@@ -16,9 +16,10 @@
89 // along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
90 //
91 // Modified by Anders Logg 2010-2011
92+// Modified by Joachim B Haga 2012
93 //
94 // First added: 2009-12-06
95-// Last changed: 2011-11-13
96+// Last changed: 2012-02-23
97
98 #ifndef __DOLFIN_ARRAY_H
99 #define __DOLFIN_ARRAY_H
100@@ -26,8 +27,7 @@
101 #include <sstream>
102 #include <string>
103 #include <utility>
104-#include <boost/shared_array.hpp>
105-
106+#include <vector>
107
108 #include <dolfin/common/constants.h>
109 #include <dolfin/common/types.h>
110@@ -44,55 +44,46 @@
111
112 template <typename T> class Array
113 {
114+
115 public:
116
117- /// Create empty array
118- Array() : _size(0), x(0) {}
119-
120- /// Create array of size N
121- explicit Array(uint N) : _size(N), x(new T[N]) {}
122-
123- /// Copy constructor (arg name need to have a different name that 'x')
124- Array(const Array& other) : _size(0), x(0)
125- { *this = other; }
126-
127- /// Construct array from a shared pointer
128- Array(uint N, boost::shared_array<T> x) : _size(N), x(x) {}
129-
130- /// Construct array from a pointer. Array will not take ownership.
131- Array(uint N, T* x) : _size(N), x(boost::shared_array<T>(x, NoDeleter())) {}
132-
133- /// Assignment operator
134- const Array& operator= (const Array& x)
135+ /// Create an empty array, with ownership. Must be resized or assigned to to be of any use.
136+ explicit Array() : _size(0), _x(NULL), _owner(true) {}
137+
138+ /// Create array of size N. Array has ownership.
139+ explicit Array(uint N) : _size(N), _x(new T[N]), _owner(true) {}
140+
141+ /// Create an array wrapping a std::vector. Array does not take ownership.
142+ explicit Array(std::vector<T>& vec) : _size(vec.size()), _x(&vec[0]), _owner(false) {}
143+
144+ /// Construct array from a pointer. Array does not take ownership.
145+ Array(uint N, T* x) : _size(N), _x(x), _owner(false) {}
146+
147+ /// Destructor.
148+ ~Array()
149 {
150- // Resize if necessary
151- if (x.empty() && !x.x)
152- {
153- this->x.reset();
154- this->_size = 0;
155- }
156- else if (this->_size != x.size())
157- {
158- this->x.reset(new T[x.size()]);
159- this->_size = x.size();
160- }
161-
162- // Copy data
163- if (_size > 0)
164- {
165- dolfin_assert(this->x);
166- dolfin_assert(x.x);
167- std::copy(&x.x[0], &x.x[_size], &this->x[0]);
168- }
169-
170- return *this;
171+ if (_owner && _x)
172+ delete[] _x;
173 }
174
175- /// Construct array from a pointer. Array will not take ownership.
176- void update(uint N, T* _x)
177+ /// Resize the array. If the new size if different from the old size, the
178+ /// Array must be owner; the old contents are then lost.
179+ void resize(uint N)
180 {
181+ if (_size == N)
182+ return;
183+ if (!_owner)
184+ dolfin_error("Array.h", "resize", "Only owned arrays can be resized");
185+ if (_x)
186+ delete[] _x;
187+ _x = (N == 0 ? NULL : new T[N]);
188 _size = N;
189- x.reset(_x, NoDeleter());
190+ }
191+
192+ /// Clear the array (resize to 0).
193+ void clear()
194+ {
195+ resize(0);
196 }
197
198 /// Return informal string representation (pretty-print).
199@@ -116,101 +107,64 @@
200 return s.str();
201 }
202
203- /// Clear array
204- void clear()
205- {
206- this->x.reset();
207- this->_size = 0;
208- }
209-
210- /// Resize array to size N. If size changes, contents will be destroyed.
211- void resize(uint N)
212- {
213- // Special case
214- if (N == _size)
215- return;
216-
217- // Special case
218- if (N == 0)
219- {
220- clear();
221- return;
222- }
223-
224- // FIXME: Do we want to allow resizing of shared data?
225- if (x.unique())
226- {
227- _size = N;
228- x.reset(new T[N]);
229- }
230- else
231- {
232- dolfin_error("Array.h",
233- "resize Array",
234- "Data is shared");
235- }
236- }
237-
238- /// Return true if empty
239- bool empty() const
240- { return _size == 0; }
241-
242 /// Return size of array
243 uint size() const
244 { return _size; }
245
246- /// Zero array
247- void zero()
248- { dolfin_assert(x); std::fill(&x[0], &x[_size], 0.0); }
249-
250 /// Set entries which meet (abs(x[i]) < eps) to zero
251 void zero_eps(double eps=DOLFIN_EPS);
252
253- /// Return minimum value of array
254- T min() const
255- { dolfin_assert(x); return *std::min_element(&x[0], &x[_size]); }
256-
257- /// Return maximum value of array
258- T max() const
259- { dolfin_assert(x); return *std::max_element(&x[0], &x[_size]); }
260-
261 /// Access value of given entry (const version)
262 const T& operator[] (uint i) const
263- { dolfin_assert(x); dolfin_assert(i < _size); return x[i]; }
264+ { dolfin_assert(i < _size); return _x[i]; }
265
266 /// Access value of given entry (non-const version)
267 T& operator[] (uint i)
268+ { dolfin_assert(i < _size); return _x[i]; }
269+
270+ /// Assignment operator. If resize is required, the Array must be owner.
271+ Array& operator= (const Array& other)
272 {
273- dolfin_assert(x);
274- dolfin_assert(i < _size);
275- return x[i];
276+ resize(other._size);
277+ if (_size > 0)
278+ std::copy(&other._x[0], &other._x[_size], &_x[0]);
279+ return *this;
280 }
281
282- /// Assign value to all entries
283- const Array<T>& operator= (T& x)
284+ /// Assignment operator from std::vector. If resize is required, the Array must be owner.
285+ Array& operator= (const std::vector<T>& other)
286 {
287- dolfin_assert(this->x);
288- for (uint i = 0; i < _size; ++i)
289- this->x[i] = x;
290+ resize(other.size());
291+ if (_size > 0)
292+ std::copy(&other[0], &other[_size], &_x[0]);
293 return *this;
294 }
295
296 /// Return pointer to data (const version)
297- const boost::shared_array<T> data() const
298- { return x; }
299+ const T* data() const
300+ { return _x; }
301
302 /// Return pointer to data (non-const version)
303- boost::shared_array<T> data()
304- { return x; }
305+ T* data()
306+ { return _x; }
307+
308+ private:
309+
310+ /// Disable copy construction, to avoid unanticipated sharing or
311+ /// copying of data. This means that an Array must always be passed as
312+ /// reference, or as a (possibly shared) pointer.
313+ Array(const Array& other) /* leave body undefined */;
314
315 private:
316
317- // Length of array
318+ /// Length of array
319 uint _size;
320
321- // Array data
322- boost::shared_array<T> x;
323+ /// Array data
324+ T* _x;
325
326+ /// True if instance is owner of data
327+ bool _owner;
328 };
329
330 template <typename T>
331@@ -224,11 +178,10 @@
332 template <>
333 inline void Array<double>::zero_eps(double eps)
334 {
335- dolfin_assert(x);
336 for (uint i = 0; i < _size; ++i)
337 {
338- if (std::abs(x[i]) < eps)
339- x[i] = 0.0;
340+ if (std::abs(_x[i]) < eps)
341+ _x[i] = 0.0;
342 }
343 }
344
345
346=== modified file 'dolfin/function/Function.cpp'
347--- dolfin/function/Function.cpp 2012-03-01 12:01:06 +0000
348+++ dolfin/function/Function.cpp 2012-03-07 13:15:44 +0000
349@@ -315,7 +315,7 @@
350 const Mesh& mesh = *_function_space->mesh();
351
352 // Find the cell that contains x
353- const double* _x = x.data().get();
354+ const double* _x = x.data();
355 const Point point(mesh.geometry().dim(), _x);
356 int id = mesh.intersected_cell(point);
357
358@@ -440,7 +440,7 @@
359 dolfin_assert(_function_space->mesh());
360 const Mesh& mesh = *_function_space->mesh();
361
362- const double* _x = x.data().get();
363+ const double* _x = x.data();
364 const uint dim = mesh.geometry().dim();
365 const Point point(dim, _x);
366
367
368=== modified file 'dolfin/graph/ZoltanInterface.cpp'
369--- dolfin/graph/ZoltanInterface.cpp 2011-11-18 12:14:50 +0000
370+++ dolfin/graph/ZoltanInterface.cpp 2012-03-07 13:15:44 +0000
371@@ -72,7 +72,7 @@
372 // Call Zoltan function to compute coloring
373 int num_id = 1;
374 int rc = zoltan.Color(num_id, graph.size(), &global_ids[0],
375- reinterpret_cast<int*>(colors.data().get()));
376+ reinterpret_cast<int*>(colors.data()));
377 if (rc != ZOLTAN_OK)
378 {
379 dolfin_error("ZoltanInterface.cpp",
380
381=== modified file 'dolfin/io/BinaryFile.cpp'
382--- dolfin/io/BinaryFile.cpp 2012-03-01 12:01:06 +0000
383+++ dolfin/io/BinaryFile.cpp 2012-03-07 13:15:44 +0000
384@@ -65,7 +65,7 @@
385
386 const uint n = read_uint();
387 Array<double> values(n);
388- read_array(n, values.data().get());
389+ read_array(n, values.data());
390
391 vector.resize(n);
392 vector.set_local(values);
393@@ -148,7 +148,7 @@
394 Array<double> values(n);
395 vector.get_local(values);
396 write_uint(n);
397- write_array(n, values.data().get());
398+ write_array(n, values.data());
399
400 close_write();
401 }
402
403=== modified file 'dolfin/io/XMLFunctionData.cpp'
404--- dolfin/io/XMLFunctionData.cpp 2011-11-18 12:14:50 +0000
405+++ dolfin/io/XMLFunctionData.cpp 2012-03-07 13:15:44 +0000
406@@ -51,8 +51,8 @@
407 const FunctionSpace& V = *u.function_space();
408
409 std::vector<std::pair<uint, uint> > global_to_cell_dof;
410- Array<double> x;
411- Array<uint> indices;
412+ std::vector<double> x;
413+ std::vector<uint> indices;
414
415 const uint num_dofs = V.dim();
416
417@@ -115,7 +115,7 @@
418 indices[i] = new_index;
419 }
420
421- vector.set(x.data().get(), x.size(), indices.data().get());
422+ vector.set(&x[0], x.size(), &indices[0]);
423 }
424
425 // Finalise vector
426
427=== modified file 'dolfin/io/XMLVector.cpp'
428--- dolfin/io/XMLVector.cpp 2011-11-18 12:14:50 +0000
429+++ dolfin/io/XMLVector.cpp 2012-03-07 13:15:44 +0000
430@@ -44,7 +44,7 @@
431 read(data, indices, xml_dolfin);
432
433 // Set data (GenericVector::apply will be called by calling function)
434- x.set(data.data().get(), data.size(), indices.data().get());
435+ x.set(data.data(), data.size(), indices.data());
436 }
437 //-----------------------------------------------------------------------------
438 void XMLVector::read(Array<double>& x, Array<uint>& indices,
439
440=== modified file 'dolfin/la/EpetraVector.cpp'
441--- dolfin/la/EpetraVector.cpp 2012-03-01 12:01:06 +0000
442+++ dolfin/la/EpetraVector.cpp 2012-03-07 13:15:44 +0000
443@@ -326,7 +326,7 @@
444
445 values.resize(x->MyLength());
446
447- const int err = x->ExtractCopy(values.data().get(), 0);
448+ const int err = x->ExtractCopy(values.data(), 0);
449 if (err!= 0)
450 {
451 dolfin_error("EpetraVector.cpp",
452@@ -470,7 +470,7 @@
453 Epetra_SerialComm serial_comm = f.get_serial_comm();
454
455 // Create map for y
456- const int* _indices = reinterpret_cast<const int*>(indices.data().get());
457+ const int* _indices = reinterpret_cast<const int*>(indices.data());
458 Epetra_BlockMap target_map(indices.size(), indices.size(), _indices, 1, 0, serial_comm);
459
460 // Reset vector y
461
462=== modified file 'dolfin/la/MUMPSLUSolver.cpp'
463--- dolfin/la/MUMPSLUSolver.cpp 2011-11-02 16:03:33 +0000
464+++ dolfin/la/MUMPSLUSolver.cpp 2012-03-07 13:15:44 +0000
465@@ -159,7 +159,7 @@
466 // Gather RHS on root process and attach
467 Array<double> _b;
468 b.gather_on_zero(_b);
469- data.rhs = _b.data().get();
470+ data.rhs = _b.data();
471
472 // Scaling strategy (77 is default)
473 data.ICNTL(8) = 77;
474@@ -171,8 +171,8 @@
475
476 // Attach solution data to MUMPS object
477 data.lsol_loc = local_x_size;
478- data.sol_loc = x_local_vals.data().get();
479- data.isol_loc = reinterpret_cast<int*>(x_local_indices.data().get());
480+ data.sol_loc = x_local_vals.data();
481+ data.isol_loc = reinterpret_cast<int*>(x_local_indices.data());
482
483 // Solve problem
484 data.job = 3;
485@@ -185,8 +185,8 @@
486 x_local_indices[i]--;
487
488 // Set x values
489- x.set(x_local_vals.data().get(), x_local_indices.size(),
490- x_local_indices.data().get());
491+ x.set(x_local_vals.data(), x_local_indices.size(),
492+ x_local_indices.data());
493 x.apply("insert");
494
495 // Clean up
496
497=== modified file 'dolfin/la/PETScVector.cpp'
498--- dolfin/la/PETScVector.cpp 2012-03-01 12:01:06 +0000
499+++ dolfin/la/PETScVector.cpp 2012-03-07 13:15:44 +0000
500@@ -228,7 +228,7 @@
501 for (uint i = 0; i < local_size; ++i)
502 rows[i] = i + n0;
503
504- VecGetValues(*x, local_size, &rows[0], values.data().get());
505+ VecGetValues(*x, local_size, &rows[0], values.data());
506 }
507 //-----------------------------------------------------------------------------
508 void PETScVector::set_local(const Array<double>& values)
509@@ -251,7 +251,7 @@
510 for (uint i = 0; i < local_size; ++i)
511 rows[i] = i + n0;
512
513- VecSetValues(*x, local_size, &rows[0], values.data().get(), INSERT_VALUES);
514+ VecSetValues(*x, local_size, &rows[0], values.data(), INSERT_VALUES);
515 }
516 //-----------------------------------------------------------------------------
517 void PETScVector::add_local(const Array<double>& values)
518@@ -274,7 +274,7 @@
519 for (uint i = 0; i < local_size; ++i)
520 rows[i] = i + n0;
521
522- VecSetValues(*x, local_size, &rows[0], values.data().get(), ADD_VALUES);
523+ VecSetValues(*x, local_size, &rows[0], values.data(), ADD_VALUES);
524 }
525 //-----------------------------------------------------------------------------
526 void PETScVector::get_local(double* block, uint m, const uint* rows) const
527@@ -681,7 +681,7 @@
528 }
529
530 // Prepare data for index sets (global indices)
531- const int* global_indices = reinterpret_cast<const int*>(indices.data().get());
532+ const int* global_indices = reinterpret_cast<const int*>(indices.data());
533
534 // Prepare data for index sets (local indices)
535 const int n = indices.size();
536
537=== modified file 'dolfin/mesh/MeshSmoothing.cpp'
538--- dolfin/mesh/MeshSmoothing.cpp 2011-06-02 19:26:59 +0000
539+++ dolfin/mesh/MeshSmoothing.cpp 2012-03-07 13:15:44 +0000
540@@ -157,13 +157,12 @@
541 BoundaryMesh boundary(mesh);
542
543 const uint dim = mesh.geometry().dim();
544- Array<double> x;
545
546 // Smooth boundary
547 MeshGeometry& geometry = boundary.geometry();
548 for (uint i = 0; i < boundary.num_vertices(); i++)
549 {
550- x.update(dim, geometry.x(i));
551+ Array<double> x(dim, geometry.x(i));
552 sub_domain.snap(x);
553 }
554
555
556=== modified file 'dolfin/mesh/SubDomain.cpp'
557--- dolfin/mesh/SubDomain.cpp 2012-03-06 13:55:20 +0000
558+++ dolfin/mesh/SubDomain.cpp 2012-03-07 13:15:44 +0000
559@@ -162,9 +162,6 @@
560 // Extract exterior (non shared) facets markers
561 const MeshFunction<bool>& exterior = mesh.parallel_data().exterior_facet();
562
563- // Array for vertex coordinate
564- Array<double> x;
565-
566 // Speed up the computation by only checking each vertex once (or twice if it
567 // is on the boundary for some but not all facets).
568 RangedIndexSet boundary_visited(mesh.num_vertices());
569@@ -197,7 +194,7 @@
570 {
571 if (is_visited.insert(vertex->index()))
572 {
573- x.update(_geometric_dimension, const_cast<double*>(vertex->x()));
574+ Array<double> x(_geometric_dimension, const_cast<double*>(vertex->x()));
575 is_inside[vertex->index()] = inside(x, on_boundary);
576 }
577
578@@ -212,8 +209,8 @@
579 // Check midpoint (works also in the case when we have a single vertex)
580 if (all_points_inside)
581 {
582- x.update(_geometric_dimension,
583- const_cast<double*>(entity->midpoint().coordinates()));
584+ Array<double> x(_geometric_dimension,
585+ const_cast<double*>(entity->midpoint().coordinates()));
586 if (!inside(x, on_boundary))
587 all_points_inside = false;
588 }
589
590=== modified file 'dolfin/swig/common/post.i'
591--- dolfin/swig/common/post.i 2012-01-17 22:38:08 +0000
592+++ dolfin/swig/common/post.i 2012-03-07 13:15:44 +0000
593@@ -55,8 +55,6 @@
594 // in any typemaps
595 %feature("valuewrapper") dolfin::Array<TYPE>;
596
597-%ignore dolfin::Array<TYPE>::Array(uint N, boost::shared_array<TYPE> x);
598-
599 // Cannot construct an Array from another Array.
600 // Use NumPy Array instead
601 %ignore dolfin::Array<TYPE>::Array(const Array& other);
602@@ -72,7 +70,7 @@
603 void __setitem__(unsigned int i, const TYPE& val) { (*self)[i] = val; }
604
605 PyObject * array(){
606- return %make_numpy_array(1, TYPE_NAME)(self->size(), self->data().get(), true);
607+ return %make_numpy_array(1, TYPE_NAME)(self->size(), self->data(), true);
608 }
609
610 }
611@@ -83,7 +81,7 @@
612 //-----------------------------------------------------------------------------
613 CONST_ARRAY_IGNORES(double)
614 ARRAY_EXTENSIONS(double, Double, double)
615-ARRAY_EXTENSIONS(const double, ConstDouble, double)
616+//ARRAY_EXTENSIONS(const double, ConstDouble, double)
617 ARRAY_EXTENSIONS(unsigned int, UInt, uint)
618 ARRAY_EXTENSIONS(int, Int, int)
619
620
621=== modified file 'dolfin/swig/la/la_get_set_items.i'
622--- dolfin/swig/la/la_get_set_items.i 2012-01-17 22:38:08 +0000
623+++ dolfin/swig/la/la_get_set_items.i 2012-03-07 13:15:44 +0000
624@@ -413,10 +413,10 @@
625 dolfin::Array<double>* values = new dolfin::Array<double>(inds->size());
626 if (row)
627 // If returning a single row
628- self->get(values->data().get(), 1, &single, inds->size(), indices);
629+ self->get(values->data(), 1, &single, inds->size(), indices);
630 else
631 // If returning a single column
632- self->get(values->data().get(), inds->size(), indices, 1, &single);
633+ self->get(values->data(), inds->size(), indices, 1, &single);
634
635 // Create the return vector and set the values
636 boost::shared_ptr<dolfin::GenericVector> return_vec = self->factory().create_vector();
637
638=== modified file 'dolfin/swig/typemaps/array.i'
639--- dolfin/swig/typemaps/array.i 2012-01-30 22:44:17 +0000
640+++ dolfin/swig/typemaps/array.i 2012-03-07 13:15:44 +0000
641@@ -90,11 +90,11 @@
642 // Director typemaps for dolfin::Array
643 //-----------------------------------------------------------------------------
644 %typemap(directorin) const dolfin::Array<double>& {
645- $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data().get(), false);
646+ $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data(), false);
647 }
648
649 %typemap(directorin) dolfin::Array<double>& {
650- $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data().get(), true);
651+ $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data(), true);
652 }
653
654 //-----------------------------------------------------------------------------
655
656=== modified file 'site-packages/dolfin/compilemodules/compilemodule.py'
657--- site-packages/dolfin/compilemodules/compilemodule.py 2012-01-30 21:20:53 +0000
658+++ site-packages/dolfin/compilemodules/compilemodule.py 2012-03-07 13:15:44 +0000
659@@ -42,6 +42,11 @@
660 "expression_to_code_fragments",
661 "math_header"]
662
663+# Bump the interface version if anything changes that invalidates cached
664+# modules (not required for change in generated code, swig version or dolfin
665+# version)
666+_interface_version = 0
667+
668 # A list of supported math builtins
669 _math_builtins = [
670 # cmath functions:
671@@ -416,7 +421,8 @@
672 if module_name is "":
673 module_name = "dolfin_compile_code_%s" % hashlib.md5(repr(code) +\
674 instant.get_swig_version() +\
675- dolfin.__version__).hexdigest()
676+ dolfin.__version__ +\
677+ str(_interface_version)).hexdigest()
678 # Check the handed import files
679 if dolfin_module_import:
680 interface_files = []

Subscribers

People subscribed via source and target branches