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
=== modified file 'dolfin/adaptivity/TimeSeries.cpp'
--- dolfin/adaptivity/TimeSeries.cpp 2012-03-01 12:01:06 +0000
+++ dolfin/adaptivity/TimeSeries.cpp 2012-03-07 13:15:44 +0000
@@ -23,6 +23,7 @@
23#include <sstream>23#include <sstream>
24#include <boost/scoped_ptr.hpp>24#include <boost/scoped_ptr.hpp>
2525
26#include <dolfin/common/constants.h>
26#include <dolfin/io/File.h>27#include <dolfin/io/File.h>
27#include <dolfin/io/BinaryFile.h>28#include <dolfin/io/BinaryFile.h>
28#include <dolfin/la/GenericVector.h>29#include <dolfin/la/GenericVector.h>
@@ -207,20 +208,14 @@
207 file >> mesh;208 file >> mesh;
208}209}
209//-----------------------------------------------------------------------------210//-----------------------------------------------------------------------------
210Array<double> TimeSeries::vector_times() const211std::vector<double> TimeSeries::vector_times() const
211{212{
212 Array<double> times(_vector_times.size());213 return _vector_times;
213 for (uint i = 0; i < _vector_times.size(); i++)
214 times[i] = _vector_times[i];
215 return times;
216}214}
217//-----------------------------------------------------------------------------215//-----------------------------------------------------------------------------
218Array<double> TimeSeries::mesh_times() const216std::vector<double> TimeSeries::mesh_times() const
219{217{
220 Array<double> times(_mesh_times.size());218 return _mesh_times;
221 for (uint i = 0; i < _mesh_times.size(); i++)
222 times[i] = _mesh_times[i];
223 return times;
224}219}
225//-----------------------------------------------------------------------------220//-----------------------------------------------------------------------------
226void TimeSeries::clear()221void TimeSeries::clear()
227222
=== modified file 'dolfin/adaptivity/TimeSeries.h'
--- dolfin/adaptivity/TimeSeries.h 2011-10-24 04:11:41 +0000
+++ dolfin/adaptivity/TimeSeries.h 2012-03-07 13:15:44 +0000
@@ -22,7 +22,7 @@
22#define __TIME_SERIES_H22#define __TIME_SERIES_H
2323
24#include <string>24#include <string>
25#include <dolfin/common/Array.h>25#include <vector>
26#include <dolfin/common/Variable.h>26#include <dolfin/common/Variable.h>
2727
28namespace dolfin28namespace dolfin
@@ -104,16 +104,16 @@
104 /// Return array of sample times for vectors104 /// Return array of sample times for vectors
105 ///105 ///
106 /// *Returns*106 /// *Returns*
107 /// _Array_ <double>107 /// std::vector<double>
108 /// The times.108 /// The times.
109 Array<double> vector_times() const;109 std::vector<double> vector_times() const;
110110
111 /// Return array of sample times for meshes111 /// Return array of sample times for meshes
112 ///112 ///
113 /// *Returns*113 /// *Returns*
114 /// _Array_ <double>114 /// std::vector<double>
115 /// The times.115 /// The times.
116 Array<double> mesh_times() const;116 std::vector<double> mesh_times() const;
117117
118 /// Clear time series118 /// Clear time series
119 void clear();119 void clear();
120120
=== modified file 'dolfin/ale/HarmonicSmoothing.cpp'
--- dolfin/ale/HarmonicSmoothing.cpp 2012-02-01 07:31:55 +0000
+++ dolfin/ale/HarmonicSmoothing.cpp 2012-03-07 13:15:44 +0000
@@ -108,7 +108,7 @@
108 solve(A, x, b, "gmres", prec);108 solve(A, x, b, "gmres", prec);
109109
110 // Get new coordinates110 // Get new coordinates
111 Array<double> _new_coordinates(N, new_coordinates.data().get() + dim*N);111 Array<double> _new_coordinates(N, new_coordinates.data() + dim*N);
112 x.get_local(_new_coordinates);112 x.get_local(_new_coordinates);
113 }113 }
114114
115115
=== modified file 'dolfin/common/Array.h'
--- dolfin/common/Array.h 2012-03-01 12:01:06 +0000
+++ dolfin/common/Array.h 2012-03-07 13:15:44 +0000
@@ -16,9 +16,10 @@
16// along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.16// along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
17//17//
18// Modified by Anders Logg 2010-201118// Modified by Anders Logg 2010-2011
19// Modified by Joachim B Haga 2012
19//20//
20// First added: 2009-12-0621// First added: 2009-12-06
21// Last changed: 2011-11-1322// Last changed: 2012-02-23
2223
23#ifndef __DOLFIN_ARRAY_H24#ifndef __DOLFIN_ARRAY_H
24#define __DOLFIN_ARRAY_H25#define __DOLFIN_ARRAY_H
@@ -26,8 +27,7 @@
26#include <sstream>27#include <sstream>
27#include <string>28#include <string>
28#include <utility>29#include <utility>
29#include <boost/shared_array.hpp>30#include <vector>
30
3131
32#include <dolfin/common/constants.h>32#include <dolfin/common/constants.h>
33#include <dolfin/common/types.h>33#include <dolfin/common/types.h>
@@ -44,55 +44,46 @@
4444
45 template <typename T> class Array45 template <typename T> class Array
46 {46 {
47
47 public:48 public:
4849
49 /// Create empty array50 /// Create an empty array, with ownership. Must be resized or assigned to to be of any use.
50 Array() : _size(0), x(0) {}51 explicit Array() : _size(0), _x(NULL), _owner(true) {}
5152
52 /// Create array of size N53 /// Create array of size N. Array has ownership.
53 explicit Array(uint N) : _size(N), x(new T[N]) {}54 explicit Array(uint N) : _size(N), _x(new T[N]), _owner(true) {}
5455
55 /// Copy constructor (arg name need to have a different name that 'x')56 /// Create an array wrapping a std::vector. Array does not take ownership.
56 Array(const Array& other) : _size(0), x(0)57 explicit Array(std::vector<T>& vec) : _size(vec.size()), _x(&vec[0]), _owner(false) {}
57 { *this = other; }58
5859 /// Construct array from a pointer. Array does not take ownership.
59 /// Construct array from a shared pointer60 Array(uint N, T* x) : _size(N), _x(x), _owner(false) {}
60 Array(uint N, boost::shared_array<T> x) : _size(N), x(x) {}61
6162 /// Destructor.
62 /// Construct array from a pointer. Array will not take ownership.63 ~Array()
63 Array(uint N, T* x) : _size(N), x(boost::shared_array<T>(x, NoDeleter())) {}
64
65 /// Assignment operator
66 const Array& operator= (const Array& x)
67 {64 {
68 // Resize if necessary65 if (_owner && _x)
69 if (x.empty() && !x.x)66 delete[] _x;
70 {
71 this->x.reset();
72 this->_size = 0;
73 }
74 else if (this->_size != x.size())
75 {
76 this->x.reset(new T[x.size()]);
77 this->_size = x.size();
78 }
79
80 // Copy data
81 if (_size > 0)
82 {
83 dolfin_assert(this->x);
84 dolfin_assert(x.x);
85 std::copy(&x.x[0], &x.x[_size], &this->x[0]);
86 }
87
88 return *this;
89 }67 }
9068
91 /// Construct array from a pointer. Array will not take ownership.69 /// Resize the array. If the new size if different from the old size, the
92 void update(uint N, T* _x)70 /// Array must be owner; the old contents are then lost.
71 void resize(uint N)
93 {72 {
73 if (_size == N)
74 return;
75 if (!_owner)
76 dolfin_error("Array.h", "resize", "Only owned arrays can be resized");
77 if (_x)
78 delete[] _x;
79 _x = (N == 0 ? NULL : new T[N]);
94 _size = N;80 _size = N;
95 x.reset(_x, NoDeleter());81 }
82
83 /// Clear the array (resize to 0).
84 void clear()
85 {
86 resize(0);
96 }87 }
9788
98 /// Return informal string representation (pretty-print).89 /// Return informal string representation (pretty-print).
@@ -116,101 +107,64 @@
116 return s.str();107 return s.str();
117 }108 }
118109
119 /// Clear array
120 void clear()
121 {
122 this->x.reset();
123 this->_size = 0;
124 }
125
126 /// Resize array to size N. If size changes, contents will be destroyed.
127 void resize(uint N)
128 {
129 // Special case
130 if (N == _size)
131 return;
132
133 // Special case
134 if (N == 0)
135 {
136 clear();
137 return;
138 }
139
140 // FIXME: Do we want to allow resizing of shared data?
141 if (x.unique())
142 {
143 _size = N;
144 x.reset(new T[N]);
145 }
146 else
147 {
148 dolfin_error("Array.h",
149 "resize Array",
150 "Data is shared");
151 }
152 }
153
154 /// Return true if empty
155 bool empty() const
156 { return _size == 0; }
157
158 /// Return size of array110 /// Return size of array
159 uint size() const111 uint size() const
160 { return _size; }112 { return _size; }
161113
162 /// Zero array
163 void zero()
164 { dolfin_assert(x); std::fill(&x[0], &x[_size], 0.0); }
165
166 /// Set entries which meet (abs(x[i]) < eps) to zero114 /// Set entries which meet (abs(x[i]) < eps) to zero
167 void zero_eps(double eps=DOLFIN_EPS);115 void zero_eps(double eps=DOLFIN_EPS);
168116
169 /// Return minimum value of array
170 T min() const
171 { dolfin_assert(x); return *std::min_element(&x[0], &x[_size]); }
172
173 /// Return maximum value of array
174 T max() const
175 { dolfin_assert(x); return *std::max_element(&x[0], &x[_size]); }
176
177 /// Access value of given entry (const version)117 /// Access value of given entry (const version)
178 const T& operator[] (uint i) const118 const T& operator[] (uint i) const
179 { dolfin_assert(x); dolfin_assert(i < _size); return x[i]; }119 { dolfin_assert(i < _size); return _x[i]; }
180120
181 /// Access value of given entry (non-const version)121 /// Access value of given entry (non-const version)
182 T& operator[] (uint i)122 T& operator[] (uint i)
123 { dolfin_assert(i < _size); return _x[i]; }
124
125 /// Assignment operator. If resize is required, the Array must be owner.
126 Array& operator= (const Array& other)
183 {127 {
184 dolfin_assert(x);128 resize(other._size);
185 dolfin_assert(i < _size);129 if (_size > 0)
186 return x[i];130 std::copy(&other._x[0], &other._x[_size], &_x[0]);
131 return *this;
187 }132 }
188133
189 /// Assign value to all entries134 /// Assignment operator from std::vector. If resize is required, the Array must be owner.
190 const Array<T>& operator= (T& x)135 Array& operator= (const std::vector<T>& other)
191 {136 {
192 dolfin_assert(this->x);137 resize(other.size());
193 for (uint i = 0; i < _size; ++i)138 if (_size > 0)
194 this->x[i] = x;139 std::copy(&other[0], &other[_size], &_x[0]);
195 return *this;140 return *this;
196 }141 }
197142
198 /// Return pointer to data (const version)143 /// Return pointer to data (const version)
199 const boost::shared_array<T> data() const144 const T* data() const
200 { return x; }145 { return _x; }
201146
202 /// Return pointer to data (non-const version)147 /// Return pointer to data (non-const version)
203 boost::shared_array<T> data()148 T* data()
204 { return x; }149 { return _x; }
150
151 private:
152
153 /// Disable copy construction, to avoid unanticipated sharing or
154 /// copying of data. This means that an Array must always be passed as
155 /// reference, or as a (possibly shared) pointer.
156 Array(const Array& other) /* leave body undefined */;
205157
206 private:158 private:
207159
208 // Length of array160 /// Length of array
209 uint _size;161 uint _size;
210162
211 // Array data163 /// Array data
212 boost::shared_array<T> x;164 T* _x;
213165
166 /// True if instance is owner of data
167 bool _owner;
214 };168 };
215169
216 template <typename T>170 template <typename T>
@@ -224,11 +178,10 @@
224 template <>178 template <>
225 inline void Array<double>::zero_eps(double eps)179 inline void Array<double>::zero_eps(double eps)
226 {180 {
227 dolfin_assert(x);
228 for (uint i = 0; i < _size; ++i)181 for (uint i = 0; i < _size; ++i)
229 {182 {
230 if (std::abs(x[i]) < eps)183 if (std::abs(_x[i]) < eps)
231 x[i] = 0.0;184 _x[i] = 0.0;
232 }185 }
233 }186 }
234187
235188
=== modified file 'dolfin/function/Function.cpp'
--- dolfin/function/Function.cpp 2012-03-01 12:01:06 +0000
+++ dolfin/function/Function.cpp 2012-03-07 13:15:44 +0000
@@ -315,7 +315,7 @@
315 const Mesh& mesh = *_function_space->mesh();315 const Mesh& mesh = *_function_space->mesh();
316316
317 // Find the cell that contains x317 // Find the cell that contains x
318 const double* _x = x.data().get();318 const double* _x = x.data();
319 const Point point(mesh.geometry().dim(), _x);319 const Point point(mesh.geometry().dim(), _x);
320 int id = mesh.intersected_cell(point);320 int id = mesh.intersected_cell(point);
321321
@@ -440,7 +440,7 @@
440 dolfin_assert(_function_space->mesh());440 dolfin_assert(_function_space->mesh());
441 const Mesh& mesh = *_function_space->mesh();441 const Mesh& mesh = *_function_space->mesh();
442442
443 const double* _x = x.data().get();443 const double* _x = x.data();
444 const uint dim = mesh.geometry().dim();444 const uint dim = mesh.geometry().dim();
445 const Point point(dim, _x);445 const Point point(dim, _x);
446446
447447
=== modified file 'dolfin/graph/ZoltanInterface.cpp'
--- dolfin/graph/ZoltanInterface.cpp 2011-11-18 12:14:50 +0000
+++ dolfin/graph/ZoltanInterface.cpp 2012-03-07 13:15:44 +0000
@@ -72,7 +72,7 @@
72 // Call Zoltan function to compute coloring72 // Call Zoltan function to compute coloring
73 int num_id = 1;73 int num_id = 1;
74 int rc = zoltan.Color(num_id, graph.size(), &global_ids[0],74 int rc = zoltan.Color(num_id, graph.size(), &global_ids[0],
75 reinterpret_cast<int*>(colors.data().get()));75 reinterpret_cast<int*>(colors.data()));
76 if (rc != ZOLTAN_OK)76 if (rc != ZOLTAN_OK)
77 {77 {
78 dolfin_error("ZoltanInterface.cpp",78 dolfin_error("ZoltanInterface.cpp",
7979
=== modified file 'dolfin/io/BinaryFile.cpp'
--- dolfin/io/BinaryFile.cpp 2012-03-01 12:01:06 +0000
+++ dolfin/io/BinaryFile.cpp 2012-03-07 13:15:44 +0000
@@ -65,7 +65,7 @@
6565
66 const uint n = read_uint();66 const uint n = read_uint();
67 Array<double> values(n);67 Array<double> values(n);
68 read_array(n, values.data().get());68 read_array(n, values.data());
6969
70 vector.resize(n);70 vector.resize(n);
71 vector.set_local(values);71 vector.set_local(values);
@@ -148,7 +148,7 @@
148 Array<double> values(n);148 Array<double> values(n);
149 vector.get_local(values);149 vector.get_local(values);
150 write_uint(n);150 write_uint(n);
151 write_array(n, values.data().get());151 write_array(n, values.data());
152152
153 close_write();153 close_write();
154}154}
155155
=== modified file 'dolfin/io/XMLFunctionData.cpp'
--- dolfin/io/XMLFunctionData.cpp 2011-11-18 12:14:50 +0000
+++ dolfin/io/XMLFunctionData.cpp 2012-03-07 13:15:44 +0000
@@ -51,8 +51,8 @@
51 const FunctionSpace& V = *u.function_space();51 const FunctionSpace& V = *u.function_space();
5252
53 std::vector<std::pair<uint, uint> > global_to_cell_dof;53 std::vector<std::pair<uint, uint> > global_to_cell_dof;
54 Array<double> x;54 std::vector<double> x;
55 Array<uint> indices;55 std::vector<uint> indices;
5656
57 const uint num_dofs = V.dim();57 const uint num_dofs = V.dim();
5858
@@ -115,7 +115,7 @@
115 indices[i] = new_index;115 indices[i] = new_index;
116 }116 }
117117
118 vector.set(x.data().get(), x.size(), indices.data().get());118 vector.set(&x[0], x.size(), &indices[0]);
119 }119 }
120120
121 // Finalise vector121 // Finalise vector
122122
=== modified file 'dolfin/io/XMLVector.cpp'
--- dolfin/io/XMLVector.cpp 2011-11-18 12:14:50 +0000
+++ dolfin/io/XMLVector.cpp 2012-03-07 13:15:44 +0000
@@ -44,7 +44,7 @@
44 read(data, indices, xml_dolfin);44 read(data, indices, xml_dolfin);
4545
46 // Set data (GenericVector::apply will be called by calling function)46 // Set data (GenericVector::apply will be called by calling function)
47 x.set(data.data().get(), data.size(), indices.data().get());47 x.set(data.data(), data.size(), indices.data());
48}48}
49//-----------------------------------------------------------------------------49//-----------------------------------------------------------------------------
50void XMLVector::read(Array<double>& x, Array<uint>& indices,50void XMLVector::read(Array<double>& x, Array<uint>& indices,
5151
=== modified file 'dolfin/la/EpetraVector.cpp'
--- dolfin/la/EpetraVector.cpp 2012-03-01 12:01:06 +0000
+++ dolfin/la/EpetraVector.cpp 2012-03-07 13:15:44 +0000
@@ -326,7 +326,7 @@
326326
327 values.resize(x->MyLength());327 values.resize(x->MyLength());
328328
329 const int err = x->ExtractCopy(values.data().get(), 0);329 const int err = x->ExtractCopy(values.data(), 0);
330 if (err!= 0)330 if (err!= 0)
331 {331 {
332 dolfin_error("EpetraVector.cpp",332 dolfin_error("EpetraVector.cpp",
@@ -470,7 +470,7 @@
470 Epetra_SerialComm serial_comm = f.get_serial_comm();470 Epetra_SerialComm serial_comm = f.get_serial_comm();
471471
472 // Create map for y472 // Create map for y
473 const int* _indices = reinterpret_cast<const int*>(indices.data().get());473 const int* _indices = reinterpret_cast<const int*>(indices.data());
474 Epetra_BlockMap target_map(indices.size(), indices.size(), _indices, 1, 0, serial_comm);474 Epetra_BlockMap target_map(indices.size(), indices.size(), _indices, 1, 0, serial_comm);
475475
476 // Reset vector y476 // Reset vector y
477477
=== modified file 'dolfin/la/MUMPSLUSolver.cpp'
--- dolfin/la/MUMPSLUSolver.cpp 2011-11-02 16:03:33 +0000
+++ dolfin/la/MUMPSLUSolver.cpp 2012-03-07 13:15:44 +0000
@@ -159,7 +159,7 @@
159 // Gather RHS on root process and attach159 // Gather RHS on root process and attach
160 Array<double> _b;160 Array<double> _b;
161 b.gather_on_zero(_b);161 b.gather_on_zero(_b);
162 data.rhs = _b.data().get();162 data.rhs = _b.data();
163163
164 // Scaling strategy (77 is default)164 // Scaling strategy (77 is default)
165 data.ICNTL(8) = 77;165 data.ICNTL(8) = 77;
@@ -171,8 +171,8 @@
171171
172 // Attach solution data to MUMPS object172 // Attach solution data to MUMPS object
173 data.lsol_loc = local_x_size;173 data.lsol_loc = local_x_size;
174 data.sol_loc = x_local_vals.data().get();174 data.sol_loc = x_local_vals.data();
175 data.isol_loc = reinterpret_cast<int*>(x_local_indices.data().get());175 data.isol_loc = reinterpret_cast<int*>(x_local_indices.data());
176176
177 // Solve problem177 // Solve problem
178 data.job = 3;178 data.job = 3;
@@ -185,8 +185,8 @@
185 x_local_indices[i]--;185 x_local_indices[i]--;
186186
187 // Set x values187 // Set x values
188 x.set(x_local_vals.data().get(), x_local_indices.size(),188 x.set(x_local_vals.data(), x_local_indices.size(),
189 x_local_indices.data().get());189 x_local_indices.data());
190 x.apply("insert");190 x.apply("insert");
191191
192 // Clean up192 // Clean up
193193
=== modified file 'dolfin/la/PETScVector.cpp'
--- dolfin/la/PETScVector.cpp 2012-03-01 12:01:06 +0000
+++ dolfin/la/PETScVector.cpp 2012-03-07 13:15:44 +0000
@@ -228,7 +228,7 @@
228 for (uint i = 0; i < local_size; ++i)228 for (uint i = 0; i < local_size; ++i)
229 rows[i] = i + n0;229 rows[i] = i + n0;
230230
231 VecGetValues(*x, local_size, &rows[0], values.data().get());231 VecGetValues(*x, local_size, &rows[0], values.data());
232}232}
233//-----------------------------------------------------------------------------233//-----------------------------------------------------------------------------
234void PETScVector::set_local(const Array<double>& values)234void PETScVector::set_local(const Array<double>& values)
@@ -251,7 +251,7 @@
251 for (uint i = 0; i < local_size; ++i)251 for (uint i = 0; i < local_size; ++i)
252 rows[i] = i + n0;252 rows[i] = i + n0;
253253
254 VecSetValues(*x, local_size, &rows[0], values.data().get(), INSERT_VALUES);254 VecSetValues(*x, local_size, &rows[0], values.data(), INSERT_VALUES);
255}255}
256//-----------------------------------------------------------------------------256//-----------------------------------------------------------------------------
257void PETScVector::add_local(const Array<double>& values)257void PETScVector::add_local(const Array<double>& values)
@@ -274,7 +274,7 @@
274 for (uint i = 0; i < local_size; ++i)274 for (uint i = 0; i < local_size; ++i)
275 rows[i] = i + n0;275 rows[i] = i + n0;
276276
277 VecSetValues(*x, local_size, &rows[0], values.data().get(), ADD_VALUES);277 VecSetValues(*x, local_size, &rows[0], values.data(), ADD_VALUES);
278}278}
279//-----------------------------------------------------------------------------279//-----------------------------------------------------------------------------
280void PETScVector::get_local(double* block, uint m, const uint* rows) const280void PETScVector::get_local(double* block, uint m, const uint* rows) const
@@ -681,7 +681,7 @@
681 }681 }
682682
683 // Prepare data for index sets (global indices)683 // Prepare data for index sets (global indices)
684 const int* global_indices = reinterpret_cast<const int*>(indices.data().get());684 const int* global_indices = reinterpret_cast<const int*>(indices.data());
685685
686 // Prepare data for index sets (local indices)686 // Prepare data for index sets (local indices)
687 const int n = indices.size();687 const int n = indices.size();
688688
=== modified file 'dolfin/mesh/MeshSmoothing.cpp'
--- dolfin/mesh/MeshSmoothing.cpp 2011-06-02 19:26:59 +0000
+++ dolfin/mesh/MeshSmoothing.cpp 2012-03-07 13:15:44 +0000
@@ -157,13 +157,12 @@
157 BoundaryMesh boundary(mesh);157 BoundaryMesh boundary(mesh);
158158
159 const uint dim = mesh.geometry().dim();159 const uint dim = mesh.geometry().dim();
160 Array<double> x;
161160
162 // Smooth boundary161 // Smooth boundary
163 MeshGeometry& geometry = boundary.geometry();162 MeshGeometry& geometry = boundary.geometry();
164 for (uint i = 0; i < boundary.num_vertices(); i++)163 for (uint i = 0; i < boundary.num_vertices(); i++)
165 {164 {
166 x.update(dim, geometry.x(i));165 Array<double> x(dim, geometry.x(i));
167 sub_domain.snap(x);166 sub_domain.snap(x);
168 }167 }
169168
170169
=== modified file 'dolfin/mesh/SubDomain.cpp'
--- dolfin/mesh/SubDomain.cpp 2012-03-06 13:55:20 +0000
+++ dolfin/mesh/SubDomain.cpp 2012-03-07 13:15:44 +0000
@@ -162,9 +162,6 @@
162 // Extract exterior (non shared) facets markers162 // Extract exterior (non shared) facets markers
163 const MeshFunction<bool>& exterior = mesh.parallel_data().exterior_facet();163 const MeshFunction<bool>& exterior = mesh.parallel_data().exterior_facet();
164164
165 // Array for vertex coordinate
166 Array<double> x;
167
168 // Speed up the computation by only checking each vertex once (or twice if it165 // Speed up the computation by only checking each vertex once (or twice if it
169 // is on the boundary for some but not all facets).166 // is on the boundary for some but not all facets).
170 RangedIndexSet boundary_visited(mesh.num_vertices());167 RangedIndexSet boundary_visited(mesh.num_vertices());
@@ -197,7 +194,7 @@
197 {194 {
198 if (is_visited.insert(vertex->index()))195 if (is_visited.insert(vertex->index()))
199 {196 {
200 x.update(_geometric_dimension, const_cast<double*>(vertex->x()));197 Array<double> x(_geometric_dimension, const_cast<double*>(vertex->x()));
201 is_inside[vertex->index()] = inside(x, on_boundary);198 is_inside[vertex->index()] = inside(x, on_boundary);
202 }199 }
203200
@@ -212,8 +209,8 @@
212 // Check midpoint (works also in the case when we have a single vertex)209 // Check midpoint (works also in the case when we have a single vertex)
213 if (all_points_inside)210 if (all_points_inside)
214 {211 {
215 x.update(_geometric_dimension,212 Array<double> x(_geometric_dimension,
216 const_cast<double*>(entity->midpoint().coordinates()));213 const_cast<double*>(entity->midpoint().coordinates()));
217 if (!inside(x, on_boundary))214 if (!inside(x, on_boundary))
218 all_points_inside = false;215 all_points_inside = false;
219 }216 }
220217
=== modified file 'dolfin/swig/common/post.i'
--- dolfin/swig/common/post.i 2012-01-17 22:38:08 +0000
+++ dolfin/swig/common/post.i 2012-03-07 13:15:44 +0000
@@ -55,8 +55,6 @@
55// in any typemaps55// in any typemaps
56%feature("valuewrapper") dolfin::Array<TYPE>;56%feature("valuewrapper") dolfin::Array<TYPE>;
5757
58%ignore dolfin::Array<TYPE>::Array(uint N, boost::shared_array<TYPE> x);
59
60// Cannot construct an Array from another Array.58// Cannot construct an Array from another Array.
61// Use NumPy Array instead59// Use NumPy Array instead
62%ignore dolfin::Array<TYPE>::Array(const Array& other);60%ignore dolfin::Array<TYPE>::Array(const Array& other);
@@ -72,7 +70,7 @@
72 void __setitem__(unsigned int i, const TYPE& val) { (*self)[i] = val; }70 void __setitem__(unsigned int i, const TYPE& val) { (*self)[i] = val; }
7371
74 PyObject * array(){72 PyObject * array(){
75 return %make_numpy_array(1, TYPE_NAME)(self->size(), self->data().get(), true);73 return %make_numpy_array(1, TYPE_NAME)(self->size(), self->data(), true);
76 }74 }
7775
78}76}
@@ -83,7 +81,7 @@
83//-----------------------------------------------------------------------------81//-----------------------------------------------------------------------------
84CONST_ARRAY_IGNORES(double)82CONST_ARRAY_IGNORES(double)
85ARRAY_EXTENSIONS(double, Double, double)83ARRAY_EXTENSIONS(double, Double, double)
86ARRAY_EXTENSIONS(const double, ConstDouble, double)84//ARRAY_EXTENSIONS(const double, ConstDouble, double)
87ARRAY_EXTENSIONS(unsigned int, UInt, uint)85ARRAY_EXTENSIONS(unsigned int, UInt, uint)
88ARRAY_EXTENSIONS(int, Int, int)86ARRAY_EXTENSIONS(int, Int, int)
8987
9088
=== modified file 'dolfin/swig/la/la_get_set_items.i'
--- dolfin/swig/la/la_get_set_items.i 2012-01-17 22:38:08 +0000
+++ dolfin/swig/la/la_get_set_items.i 2012-03-07 13:15:44 +0000
@@ -413,10 +413,10 @@
413 dolfin::Array<double>* values = new dolfin::Array<double>(inds->size());413 dolfin::Array<double>* values = new dolfin::Array<double>(inds->size());
414 if (row)414 if (row)
415 // If returning a single row415 // If returning a single row
416 self->get(values->data().get(), 1, &single, inds->size(), indices);416 self->get(values->data(), 1, &single, inds->size(), indices);
417 else417 else
418 // If returning a single column418 // If returning a single column
419 self->get(values->data().get(), inds->size(), indices, 1, &single);419 self->get(values->data(), inds->size(), indices, 1, &single);
420420
421 // Create the return vector and set the values421 // Create the return vector and set the values
422 boost::shared_ptr<dolfin::GenericVector> return_vec = self->factory().create_vector();422 boost::shared_ptr<dolfin::GenericVector> return_vec = self->factory().create_vector();
423423
=== modified file 'dolfin/swig/typemaps/array.i'
--- dolfin/swig/typemaps/array.i 2012-01-30 22:44:17 +0000
+++ dolfin/swig/typemaps/array.i 2012-03-07 13:15:44 +0000
@@ -90,11 +90,11 @@
90// Director typemaps for dolfin::Array90// Director typemaps for dolfin::Array
91//-----------------------------------------------------------------------------91//-----------------------------------------------------------------------------
92%typemap(directorin) const dolfin::Array<double>& {92%typemap(directorin) const dolfin::Array<double>& {
93 $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data().get(), false);93 $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data(), false);
94 }94 }
9595
96%typemap(directorin) dolfin::Array<double>& {96%typemap(directorin) dolfin::Array<double>& {
97 $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data().get(), true);97 $input = %make_numpy_array(1, double)($1_name.size(), $1_name.data(), true);
98 }98 }
9999
100//-----------------------------------------------------------------------------100//-----------------------------------------------------------------------------
101101
=== modified file 'site-packages/dolfin/compilemodules/compilemodule.py'
--- site-packages/dolfin/compilemodules/compilemodule.py 2012-01-30 21:20:53 +0000
+++ site-packages/dolfin/compilemodules/compilemodule.py 2012-03-07 13:15:44 +0000
@@ -42,6 +42,11 @@
42 "expression_to_code_fragments",42 "expression_to_code_fragments",
43 "math_header"]43 "math_header"]
4444
45# Bump the interface version if anything changes that invalidates cached
46# modules (not required for change in generated code, swig version or dolfin
47# version)
48_interface_version = 0
49
45# A list of supported math builtins50# A list of supported math builtins
46_math_builtins = [51_math_builtins = [
47 # cmath functions:52 # cmath functions:
@@ -416,7 +421,8 @@
416 if module_name is "":421 if module_name is "":
417 module_name = "dolfin_compile_code_%s" % hashlib.md5(repr(code) +\422 module_name = "dolfin_compile_code_%s" % hashlib.md5(repr(code) +\
418 instant.get_swig_version() +\423 instant.get_swig_version() +\
419 dolfin.__version__).hexdigest()424 dolfin.__version__ +\
425 str(_interface_version)).hexdigest()
420 # Check the handed import files426 # Check the handed import files
421 if dolfin_module_import:427 if dolfin_module_import:
422 interface_files = []428 interface_files = []

Subscribers

People subscribed via source and target branches