Open EmilyBourne opened 6 months ago
I am thinking of defining a ddc::Chunk
/ddc::ChunkSpan
not only over a ddc::DiscreteDomain
but over a cartesian product of 1D ranges of ddc::DiscreteElement
. In this case ddc::DiscreteDomain
would be the particular case of a cartesian product of 1D continuous ranges. This way we could also introduce a strided range of ddc::DiscreteElement
.
Accessing ddc::Chunk
/ddc::ChunkSpan
data using ddc::DiscreteElement
could be slow depending on the type of range. For other reasons I would also like to introduce an access using ddc::DiscreteVector
that would always be "fast" compared to the latter.
Do you think it would help you ?
This sounds like it would cover our use cases as described in the issue. I'm not sure I have fully understood though. The Chunk
/ChunkSpan
would depend on both a DiscreteDomain
and a Range
?
I can see a use for 3 kinds of ranges:
@pauline987654321 has recently come across a use case for the generala case.
For other reasons I would also like to introduce an access using
ddc::DiscreteVector
that would always be "fast" compared to the latter.
This sounds like a good idea in theory but I wonder if ddc::DiscreteVector
is the right tool?
It seems a little confusing to me if you have:
NewRangeType valid_indices(start_element, n_elements, stride_length);
Chunk my_chunk(valid_indices);
ddc::DiscreteVector step(3);
my_chunk(start_element + step) != my_chunk(step) // start_element + step != start_element + step * stride_length
This sounds like it would cover our use cases as described in the issue. I'm not sure I have fully understood though. The
Chunk
/ChunkSpan
would depend on both aDiscreteDomain
and aRange
?
No I was thinking of only one parameter describing the Support
of the Chunk
/ChunkSpan
, for example something like ChunkSpan<double, StridedDomain<DDimX, DDimY>>
.
- arbitrary (ordered) range (general case)
Yes, it seems more difficult but should be doable. However accessing it using DiscreteElement
would be more costly because of the lookup.
This sounds like a good idea in theory but I wonder if
ddc::DiscreteVector
is the right tool? It seems a little confusing to me if you have:NewRangeType valid_indices(start_element, n_elements, stride_length); Chunk my_chunk(valid_indices); ddc::DiscreteVector step(3); my_chunk(start_element + step) != my_chunk(step) // start_element + step != start_element + step * stride_length
To me you would have to wonder if the element belongs to the range, which is not the case in your example start_element + step
does not belong to valid_indices
. Then you cannot call my_chunk(start_element + step)
because it does not define any attribute associated to the element start_element + step
. The third element in valid_indices
would be valid_indices(step)
/valid_indices[step]
and this element could be used to get the attribute with my_chunk(valid_indices(step))
, even though my_chunk(step)
would be both easier to read and faster.
No I was thinking of only one parameter
Sounds good
Yes, it seems more difficult but should be doable. However accessing it using DiscreteElement would be more costly because of the lookup.
Yes that makes sense
To me you would have to wonder if the element belongs to the range, which is not the case in your example
start_element + step
does not belong tovalid_indices
If stride_length is 3 then start_element + step
does belong to valid_indices
valid_indices(step)/valid_indices[step]
So you would use operator()
for access via indices and operator[]
for access via offset? That makes sense but could definitely be a trip hasard for new users
If stride_length is 3 then
start_element + step
does belong tovalid_elements
Oh that is true, then it would be the second element in valid_elements
, so something like this should work
ddc::DiscreteVector range_stride(3);
StridedDomain valid_elements(start_element, n_elements, range_stride);
ddc::Chunk<int, StridedDomain> my_chunk(valid_elements);
EXPECT_EQUAL(my_chunk(ddc::DiscreteVector(0)), my_chunk(start_element));
EXPECT_EQUAL(my_chunk(ddc::DiscreteVector(1)), my_chunk(start_element + range_stride));
EXPECT_EQUAL(my_chunk(ddc::DiscreteVector(1)), my_chunk(valid_elements(ddc::DiscreteVector(1))));
Would this make sense ?
valid_elements(step)/valid_elements[step]
So you would use
operator()
for access via indices andoperator[]
for access via offset? That makes sense but could definitely be a trip hasard for new users
No I meant one of the two operators would allow to access the n-th element using a DiscreteVector
, I just don't know yet which one.
Then this looks good to me. Presumably an iterator would then use a ddc::DiscreteVector
internally?
Could be yes
Then that all sounds ok to me. What would a for_each
loop look like in this case?
ddc::DiscreteVector range_stride(2);
StridedDomain valid_elements(start_element, n_elements, range_stride);
ddc::Chunk<int, StridedDomain> my_chunk(valid_elements);
// Option 1
for_each (valid_elements, [&](ddc::DiscreteElement<IDim> idx) {
my_chunk(idx) = ddc::coordinate(idx);
}
// Option 2
for_each (valid_elements, [&](ddc::DiscreteVector<IDim> vec) {
my_chunk(valid_elements(vec)) = ddc::coordinate(start_element + vec);
}
// Option 3
for_each (valid_elements, [&](ChunkIterator iter) {
ddc::DiscreteElement idx = iter.element();
my_chunk(iter) = ddc::coordinate(idx);
}
Something else?
I think we can define algorithms for the options 1 and 2.
I can see a use for 3 kinds of ranges:
- continuous range (equivalent to the current behaviour)
- strided range (as described in the issue)
- arbitrary (ordered) range (general case)
@pauline987654321 has recently come across a use case for the generala case.
Back to this comment, in 3. would it require storage or would there be an analytical formula ?
It would require storage. We won't always have an analytical formula.
I would like to be able to create some kind of SubDomain. For example this could be achieved by adding a stride to the Domain. This would be useful in several places.
It can be used to iterate over a sliced domain. This can be useful for creating a Lagrange interpolation or calculating a quadrature (e.g. Simpson's quadrature). E.g. currently a Simpson's quadrature is written as:
with a SubDomain it would be:
It can also be used to create a Chunk on a SubDomain. Eg when working with patches it is common to need values of a function over all the domain, but the derivatives only at certain points (usually the boundary). Currently this is only possible by explicitly choosing the number of points at the compilation, or creating a separate mesh for the derivatives (which then have different
DiscreteElements
)