Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Grid_Array.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_GRID_ARRAY_HPP
17#define CABANA_GRID_ARRAY_HPP
18
22#include <Cabana_Grid_Types.hpp>
23
24#include <Kokkos_Core.hpp>
25
26#include <cmath>
27#include <memory>
28#include <type_traits>
29#include <vector>
30
31#include <mpi.h>
32
33namespace Cabana
34{
35namespace Grid
36{
37//---------------------------------------------------------------------------//
44template <class EntityType, class MeshType>
46{
47 public:
49 using entity_type = EntityType;
50
52 using mesh_type = MeshType;
53
55 static constexpr std::size_t num_space_dim = mesh_type::num_space_dim;
56
63 ArrayLayout( const std::shared_ptr<LocalGrid<MeshType>>& local_grid,
64 const int dofs_per_entity )
65 : _local_grid( local_grid )
66 , _dofs_per_entity( dofs_per_entity )
67 {
68 }
69
71 const std::shared_ptr<LocalGrid<MeshType>> localGrid() const
72 {
73 return _local_grid;
74 }
75
77 int dofsPerEntity() const { return _dofs_per_entity; }
78
81 template <class DecompositionTag, class IndexType>
83 indexSpace( DecompositionTag decomposition_tag, IndexType index_type ) const
84 {
85 return appendDimension( _local_grid->indexSpace( decomposition_tag,
86 EntityType(),
87 index_type ),
88 _dofs_per_entity );
89 }
90
101 template <class DecompositionTag>
103 sharedIndexSpace( DecompositionTag decomposition_tag,
104 const std::array<int, num_space_dim>& off_ijk,
105 const int halo_width = -1 ) const
106 {
107 return appendDimension(
108 _local_grid->sharedIndexSpace( decomposition_tag, EntityType(),
109 off_ijk, halo_width ),
110 _dofs_per_entity );
111 }
112
123 template <class DecompositionTag, std::size_t NSD = num_space_dim>
124 std::enable_if_t<3 == NSD, IndexSpace<4>>
125 sharedIndexSpace( DecompositionTag decomposition_tag, const int off_i,
126 const int off_j, const int off_k,
127 const int halo_width = -1 ) const
128 {
129 std::array<int, 3> off_ijk = { off_i, off_j, off_k };
130 return sharedIndexSpace( decomposition_tag, off_ijk, halo_width );
131 }
132
143 template <class DecompositionTag, std::size_t NSD = num_space_dim>
144 std::enable_if_t<2 == NSD, IndexSpace<3>>
145 sharedIndexSpace( DecompositionTag decomposition_tag, const int off_i,
146 const int off_j, const int halo_width = -1 ) const
147 {
148 std::array<int, 2> off_ijk = { off_i, off_j };
149 return sharedIndexSpace( decomposition_tag, off_ijk, halo_width );
150 }
151
152 private:
153 std::shared_ptr<LocalGrid<MeshType>> _local_grid;
154 int _dofs_per_entity;
155};
156
158template <class>
159struct is_array_layout : public std::false_type
160{
161};
162
164template <class EntityType, class MeshType>
165struct is_array_layout<ArrayLayout<EntityType, MeshType>>
166 : public std::true_type
167{
168};
169
171template <class EntityType, class MeshType>
172struct is_array_layout<const ArrayLayout<EntityType, MeshType>>
173 : public std::true_type
174{
175};
176
177//---------------------------------------------------------------------------//
178// Array layout creation.
179//---------------------------------------------------------------------------//
187template <class EntityType, class MeshType>
188std::shared_ptr<ArrayLayout<EntityType, MeshType>>
189createArrayLayout( const std::shared_ptr<LocalGrid<MeshType>>& local_grid,
190 const int dofs_per_entity, EntityType )
191{
192 return std::make_shared<ArrayLayout<EntityType, MeshType>>(
193 local_grid, dofs_per_entity );
194}
195
196//---------------------------------------------------------------------------//
208template <class EntityType, class MeshType>
209std::shared_ptr<ArrayLayout<EntityType, MeshType>>
210createArrayLayout( const std::shared_ptr<GlobalGrid<MeshType>>& global_grid,
211 const int halo_cell_width, const int dofs_per_entity,
212 EntityType )
213{
214 return std::make_shared<ArrayLayout<EntityType, MeshType>>(
215 createLocalGrid( global_grid, halo_cell_width ), dofs_per_entity );
216}
217
218//---------------------------------------------------------------------------//
227template <class Scalar, class EntityType, class MeshType, class... Params>
228class Array
229{
230 public:
232 using value_type = Scalar;
233
235 using entity_type = EntityType;
236
238 using mesh_type = MeshType;
239
241 static constexpr std::size_t num_space_dim = mesh_type::num_space_dim;
242
245
247 using view_type = std::conditional_t<
248 3 == num_space_dim, Kokkos::View<value_type****, Params...>,
249 std::conditional_t<2 == num_space_dim,
250 Kokkos::View<value_type***, Params...>, void>>;
251
253 using memory_space = typename view_type::memory_space;
255 using device_type [[deprecated]] = typename memory_space::device_type;
257 using execution_space = typename memory_space::execution_space;
258
265 Array( const std::string& label,
266 const std::shared_ptr<array_layout>& layout )
267 : _layout( layout )
268 , _data( createView<value_type, Params...>(
269 label, layout->indexSpace( Ghost(), Local() ) ) )
270 {
271 }
272
279 Array( const std::shared_ptr<array_layout>& layout, const view_type& view )
280 : _layout( layout )
281 , _data( view )
282 {
283 for ( std::size_t d = 0; d < num_space_dim + 1; ++d )
284 if ( (long)view.extent( d ) !=
285 layout->indexSpace( Ghost(), Local() ).extent( d ) )
286 throw std::runtime_error(
287 "Cabana::Grid::Array: Layout and "
288 "view dimensions do not match (View label: " +
289 view.label() + ")" );
290 }
291
293 std::shared_ptr<array_layout> layout() const { return _layout; }
294
296 view_type view() const { return _data; }
297
299 std::string label() const { return _data.label(); }
300
301 private:
302 std::shared_ptr<array_layout> _layout;
303 view_type _data;
304
305 public:
307 using subview_type = decltype( createSubview(
308 _data, _layout->indexSpace( Ghost(), Local() ) ) );
310 using subview_layout = typename subview_type::array_layout;
312 using subview_memory_traits = typename subview_type::memory_traits;
314 using subarray_type = Array<Scalar, EntityType, MeshType, subview_layout,
316};
317
318//---------------------------------------------------------------------------//
319// Static type checker.
320//---------------------------------------------------------------------------//
321// Static type checker.
322template <class>
323struct is_array : public std::false_type
324{
325};
326
327template <class Scalar, class EntityType, class MeshType, class... Params>
328struct is_array<Array<Scalar, EntityType, MeshType, Params...>>
329 : public std::true_type
330{
331};
332
333template <class Scalar, class EntityType, class MeshType, class... Params>
334struct is_array<const Array<Scalar, EntityType, MeshType, Params...>>
335 : public std::true_type
336{
337};
338
339//---------------------------------------------------------------------------//
340// Array creation.
341//---------------------------------------------------------------------------//
349template <class Scalar, class... Params, class EntityType, class MeshType>
350std::shared_ptr<Array<Scalar, EntityType, MeshType, Params...>>
351createArray( const std::string& label,
352 const std::shared_ptr<ArrayLayout<EntityType, MeshType>>& layout )
353{
354 return std::make_shared<Array<Scalar, EntityType, MeshType, Params...>>(
355 label, layout );
356}
357
358//---------------------------------------------------------------------------//
359// Subarray creation.
360//---------------------------------------------------------------------------//
369template <class Scalar, class EntityType, class MeshType, class... Params>
370std::shared_ptr<Array<
371 Scalar, EntityType, MeshType,
372 typename Array<Scalar, EntityType, MeshType, Params...>::subview_layout,
373 typename Array<Scalar, EntityType, MeshType, Params...>::memory_space,
374 typename Array<Scalar, EntityType, MeshType,
375 Params...>::subview_memory_traits>>
377 const int dof_min, const int dof_max )
378{
379 if ( dof_min < 0 || dof_max > array.layout()->dofsPerEntity() )
380 throw std::logic_error( "Cabana::Grid::createSubarray: Subarray "
381 "dimensions out of bounds (Label: " +
382 array.label() + ")" );
383
384 auto space = array.layout()->indexSpace( Ghost(), Local() );
385 std::array<long, MeshType::num_space_dim + 1> min;
386 std::array<long, MeshType::num_space_dim + 1> max;
387 for ( std::size_t d = 0; d < MeshType::num_space_dim; ++d )
388 {
389 min[d] = space.min( d );
390 max[d] = space.max( d );
391 }
392 min.back() = dof_min;
393 max.back() = dof_max;
394 IndexSpace<MeshType::num_space_dim + 1> sub_space( min, max );
395 auto sub_view = createSubview( array.view(), sub_space );
396 auto sub_layout = createArrayLayout( array.layout()->localGrid(),
397 dof_max - dof_min, EntityType() );
398 return std::make_shared<Array<
399 Scalar, EntityType, MeshType,
400 typename Array<Scalar, EntityType, MeshType, Params...>::subview_layout,
401 typename Array<Scalar, EntityType, MeshType, Params...>::memory_space,
402 typename Array<Scalar, EntityType, MeshType,
403 Params...>::subview_memory_traits>>( sub_layout,
404 sub_view );
405}
406
407//---------------------------------------------------------------------------//
408// Array operations.
409//---------------------------------------------------------------------------//
410namespace ArrayOp
411{
412//---------------------------------------------------------------------------//
417template <class Scalar, class... Params, class EntityType, class MeshType>
418std::shared_ptr<Array<Scalar, EntityType, MeshType, Params...>>
420{
421 return createArray<Scalar, Params...>( array.label(), array.layout() );
422}
423
424//---------------------------------------------------------------------------//
431template <class Array_t, class DecompositionTag>
432void assign( Array_t& array, const typename Array_t::value_type alpha,
433 DecompositionTag tag )
434{
435 static_assert(
437 "Cabana::Grid::ArrayOp::assign: Cabana::Grid::Array required" );
438 auto subview = createSubview( array.view(),
439 array.layout()->indexSpace( tag, Local() ) );
440 Kokkos::deep_copy( subview, alpha );
441}
442
443//---------------------------------------------------------------------------//
450template <class Array_t, class DecompositionTag>
451std::enable_if_t<3 == Array_t::num_space_dim, void>
452scale( Array_t& array, const typename Array_t::value_type alpha,
453 DecompositionTag tag )
454{
455 static_assert(
457 "Cabana::Grid::ArrayOp::scale: Cabana::Grid::Array required" );
458 auto view = array.view();
459 Kokkos::parallel_for(
460 "Cabana::Grid::ArrayOp::scale",
461 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
462 typename Array_t::execution_space() ),
463 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
464 view( i, j, k, l ) *= alpha;
465 } );
466}
467
474template <class Array_t, class DecompositionTag>
475std::enable_if_t<2 == Array_t::num_space_dim, void>
476scale( Array_t& array, const typename Array_t::value_type alpha,
477 DecompositionTag tag )
478{
479 static_assert(
481 "Cabana::Grid::ArrayOp::scale: Cabana::Grid::Array required" );
482 auto view = array.view();
483 Kokkos::parallel_for(
484 "Cabana::Grid::ArrayOp::scale",
485 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
486 typename Array_t::execution_space() ),
487 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
488 view( i, j, l ) *= alpha;
489 } );
490}
491
492//---------------------------------------------------------------------------//
500template <class Array_t, class DecompositionTag>
501std::enable_if_t<3 == Array_t::num_space_dim, void>
502scale( Array_t& array, const std::vector<typename Array_t::value_type>& alpha,
503 DecompositionTag tag )
504{
505 static_assert(
507 "Cabana::Grid::ArrayOp::scale: Cabana::Grid::Array required" );
508 if ( alpha.size() !=
509 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
510 throw std::runtime_error( "Cabana::Grid::ArrayOp::scale: Incorrect "
511 "vector size (Label: " +
512 array.label() + ")" );
513
514 Kokkos::View<const typename Array_t::value_type*, Kokkos::HostSpace,
515 Kokkos::MemoryUnmanaged>
516 alpha_view_host( alpha.data(), alpha.size() );
517 auto alpha_view = Kokkos::create_mirror_view_and_copy(
518 typename Array_t::memory_space(), alpha_view_host );
519
520 auto array_view = array.view();
521 Kokkos::parallel_for(
522 "Cabana::Grid::ArrayOp::scale",
523 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
524 typename Array_t::execution_space() ),
525 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
526 array_view( i, j, k, l ) *= alpha_view( l );
527 } );
528}
529
537template <class Array_t, class DecompositionTag>
538std::enable_if_t<2 == Array_t::num_space_dim, void>
539scale( Array_t& array, const std::vector<typename Array_t::value_type>& alpha,
540 DecompositionTag tag )
541{
542 static_assert(
544 "Cabana::Grid::ArrayOp::scale: Cabana::Grid::Array required" );
545 if ( alpha.size() !=
546 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
547 throw std::runtime_error( "Cabana::Grid::ArrayOp::scale: Incorrect "
548 "vector size (Label: " +
549 array.label() + ")" );
550
551 Kokkos::View<const typename Array_t::value_type*, Kokkos::HostSpace,
552 Kokkos::MemoryUnmanaged>
553 alpha_view_host( alpha.data(), alpha.size() );
554 auto alpha_view = Kokkos::create_mirror_view_and_copy(
555 typename Array_t::memory_space(), alpha_view_host );
556
557 auto array_view = array.view();
558 Kokkos::parallel_for(
559 "Cabana::Grid::ArrayOp::scale",
560 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
561 typename Array_t::execution_space() ),
562 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
563 array_view( i, j, l ) *= alpha_view( l );
564 } );
565}
566
567//---------------------------------------------------------------------------//
574template <class Array_t, class DecompositionTag>
575void copy( Array_t& a, const Array_t& b, DecompositionTag tag )
576{
577 static_assert(
579 "Cabana::Grid::ArrayOp::copy: Cabana::Grid::Array required" );
580 auto a_space = a.layout()->indexSpace( tag, Local() );
581 auto b_space = b.layout()->indexSpace( tag, Local() );
582 if ( a_space != b_space )
583 throw std::logic_error( "Cabana::Grid::ArrayOp::copy: Incompatible "
584 "index spaces (Labels: " +
585 a.label() + ", " + b.label() + ")" );
586 auto subview_a = createSubview( a.view(), a_space );
587 auto subview_b = createSubview( b.view(), b_space );
588 Kokkos::deep_copy( subview_a, subview_b );
589}
590
591//---------------------------------------------------------------------------//
597template <class Array_t, class DecompositionTag>
598std::shared_ptr<Array_t> cloneCopy( const Array_t& array, DecompositionTag tag )
599{
600 auto cln = clone( array );
601 copy( *cln, array, tag );
602 return cln;
603}
604
605//---------------------------------------------------------------------------//
615template <class Array_t, class DecompositionTag>
616std::enable_if_t<3 == Array_t::num_space_dim, void>
617update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
618 const typename Array_t::value_type beta, DecompositionTag tag )
619{
620 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
621 auto a_view = a.view();
622 auto b_view = b.view();
623 Kokkos::parallel_for(
624 "Cabana::Grid::ArrayOp::update",
625 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
626 typename Array_t::execution_space() ),
627 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
628 a_view( i, j, k, l ) =
629 alpha * a_view( i, j, k, l ) + beta * b_view( i, j, k, l );
630 } );
631}
632
642template <class Array_t, class DecompositionTag>
643std::enable_if_t<2 == Array_t::num_space_dim, void>
644update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
645 const typename Array_t::value_type beta, DecompositionTag tag )
646{
647 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
648 auto a_view = a.view();
649 auto b_view = b.view();
650 Kokkos::parallel_for(
651 "Cabana::Grid::ArrayOp::update",
652 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
653 typename Array_t::execution_space() ),
654 KOKKOS_LAMBDA( const long i, const long j, const long l ) {
655 a_view( i, j, l ) =
656 alpha * a_view( i, j, l ) + beta * b_view( i, j, l );
657 } );
658}
659
660//---------------------------------------------------------------------------//
672template <class Array_t, class DecompositionTag>
673std::enable_if_t<3 == Array_t::num_space_dim, void>
674update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
675 const typename Array_t::value_type beta, const Array_t& c,
676 const typename Array_t::value_type gamma, DecompositionTag tag )
677{
678 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
679 auto a_view = a.view();
680 auto b_view = b.view();
681 auto c_view = c.view();
682 Kokkos::parallel_for(
683 "Cabana::Grid::ArrayOp::update",
684 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
685 typename Array_t::execution_space() ),
686 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
687 a_view( i, j, k, l ) = alpha * a_view( i, j, k, l ) +
688 beta * b_view( i, j, k, l ) +
689 gamma * c_view( i, j, k, l );
690 } );
691}
692
704template <class Array_t, class DecompositionTag>
705std::enable_if_t<2 == Array_t::num_space_dim, void>
706update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
707 const typename Array_t::value_type beta, const Array_t& c,
708 const typename Array_t::value_type gamma, DecompositionTag tag )
709{
710 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
711 auto a_view = a.view();
712 auto b_view = b.view();
713 auto c_view = c.view();
714 Kokkos::parallel_for(
715 "Cabana::Grid::ArrayOp::update",
716 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
717 typename Array_t::execution_space() ),
718 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
719 a_view( i, j, l ) = alpha * a_view( i, j, l ) +
720 beta * b_view( i, j, l ) +
721 gamma * c_view( i, j, l );
722 } );
723}
724
725//---------------------------------------------------------------------------//
727template <class ViewType, std::size_t NumSpaceDim>
729{
731 static constexpr std::size_t num_space_dim = NumSpaceDim;
733 typedef typename ViewType::value_type value_type[];
735 typedef typename ViewType::size_type size_type;
739 ViewType _a;
741 ViewType _b;
742
744 DotFunctor( const ViewType& a, const ViewType& b )
745 : value_count( a.extent( NumSpaceDim ) )
746 , _a( a )
747 , _b( b )
748 {
749 }
750
752 template <std::size_t NSD = num_space_dim>
753 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
754 operator()( const size_type i, const size_type j, const size_type k,
755 const size_type l, value_type sum ) const
756 {
757 sum[l] += _a( i, j, k, l ) * _b( i, j, k, l );
758 }
759
761 template <std::size_t NSD = num_space_dim>
762 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
763 operator()( const size_type i, const size_type j, const size_type l,
764 value_type sum ) const
765 {
766 sum[l] += _a( i, j, l ) * _b( i, j, l );
767 }
768
770 KOKKOS_INLINE_FUNCTION
771 void join( value_type dst, const value_type src ) const
772 {
773 for ( size_type j = 0; j < value_count; ++j )
774 dst[j] += src[j];
775 }
776
778 KOKKOS_INLINE_FUNCTION
779 void join( volatile value_type dst, const volatile value_type src ) const
780 {
781 for ( size_type j = 0; j < value_count; ++j )
782 dst[j] += src[j];
783 }
784
786 KOKKOS_INLINE_FUNCTION void init( value_type sum ) const
787 {
788 for ( size_type j = 0; j < value_count; ++j )
789 sum[j] = 0.0;
790 }
791};
792
801template <class Array_t>
802void dot( const Array_t& a, const Array_t& b,
803 std::vector<typename Array_t::value_type>& products )
804{
805 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
806 if ( products.size() !=
807 static_cast<unsigned>( a.layout()->dofsPerEntity() ) )
808 throw std::runtime_error(
809 "Cabana::Grid::ArrayOp::dot: Incorrect vector size" );
810
811 for ( auto& p : products )
812 p = 0.0;
813
815 a.view(), b.view() );
816 typename Array_t::execution_space exec_space;
817 Kokkos::parallel_reduce(
818 "Cabana::Grid::ArrayOp::dot",
819 createExecutionPolicy( a.layout()->indexSpace( Own(), Local() ),
820 exec_space ),
821 functor,
822 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
823 products.data(), products.size() ) );
824 exec_space.fence( "Cabana::Grid::ArrayOp::dot before MPI_Allreduce" );
825
826 MPI_Allreduce( MPI_IN_PLACE, products.data(), products.size(),
828 a.layout()->localGrid()->globalGrid().comm() );
829}
830
831//---------------------------------------------------------------------------//
833template <class ViewType, std::size_t NumSpaceDim>
835{
837 static constexpr std::size_t num_space_dim = NumSpaceDim;
839 typedef typename ViewType::value_type value_type[];
841 typedef typename ViewType::size_type size_type;
845 ViewType _view;
846
848 NormInfFunctor( const ViewType& view )
849 : value_count( view.extent( NumSpaceDim ) )
850 , _view( view )
851 {
852 }
853
855 template <std::size_t NSD = num_space_dim>
856 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
857 operator()( const size_type i, const size_type j, const size_type k,
858 const size_type l, value_type norm ) const
859 {
860 auto v_abs = fabs( _view( i, j, k, l ) );
861 if ( v_abs > norm[l] )
862 norm[l] = v_abs;
863 }
864
866 template <std::size_t NSD = num_space_dim>
867 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
868 operator()( const size_type i, const size_type j, const size_type l,
869 value_type norm ) const
870 {
871 auto v_abs = fabs( _view( i, j, l ) );
872 if ( v_abs > norm[l] )
873 norm[l] = v_abs;
874 }
875
877 KOKKOS_INLINE_FUNCTION
878 void join( value_type dst, const value_type src ) const
879 {
880 for ( size_type j = 0; j < value_count; ++j )
881 if ( src[j] > dst[j] )
882 dst[j] = src[j];
883 }
884
886 KOKKOS_INLINE_FUNCTION
887 void join( volatile value_type dst, const volatile value_type src ) const
888 {
889 for ( size_type j = 0; j < value_count; ++j )
890 if ( src[j] > dst[j] )
891 dst[j] = src[j];
892 }
893
895 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
896 {
897 for ( size_type j = 0; j < value_count; ++j )
898 norm[j] = 0.0;
899 }
900};
901
908template <class Array_t>
909void normInf( const Array_t& array,
910 std::vector<typename Array_t::value_type>& norms )
911{
912 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
913 if ( norms.size() !=
914 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
915 throw std::runtime_error(
916 "Cabana::Grid::ArrayOp::normInf: Incorrect vector size" );
917
918 for ( auto& n : norms )
919 n = 0.0;
920
922 array.view() );
923 typename Array_t::execution_space exec_space;
924 Kokkos::parallel_reduce(
925 "Cabana::Grid::ArrayOp::normInf",
926 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
927 exec_space ),
928 functor,
929 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
930 norms.data(), norms.size() ) );
931 exec_space.fence( "ArrayOp::normInf before MPI_Allreduce" );
932
933 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
935 array.layout()->localGrid()->globalGrid().comm() );
936}
937
938//---------------------------------------------------------------------------//
940template <class ViewType, std::size_t NumSpaceDim>
942{
944 static constexpr std::size_t num_space_dim = NumSpaceDim;
946 typedef typename ViewType::value_type value_type[];
948 typedef typename ViewType::size_type size_type;
952 ViewType _view;
953
955 Norm1Functor( const ViewType& view )
956 : value_count( view.extent( NumSpaceDim ) )
957 , _view( view )
958 {
959 }
960
962 template <std::size_t NSD = num_space_dim>
963 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
964 operator()( const size_type i, const size_type j, const size_type k,
965 const size_type l, value_type norm ) const
966 {
967 norm[l] += fabs( _view( i, j, k, l ) );
968 }
969
971 template <std::size_t NSD = num_space_dim>
972 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
973 operator()( const size_type i, const size_type j, const size_type l,
974 value_type norm ) const
975 {
976 norm[l] += fabs( _view( i, j, l ) );
977 }
978
980 KOKKOS_INLINE_FUNCTION
981 void join( value_type dst, const value_type src ) const
982 {
983 for ( size_type j = 0; j < value_count; ++j )
984 dst[j] += src[j];
985 }
986
988 KOKKOS_INLINE_FUNCTION
989 void join( volatile value_type dst, const volatile value_type src ) const
990 {
991 for ( size_type j = 0; j < value_count; ++j )
992 dst[j] += src[j];
993 }
994
996 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
997 {
998 for ( size_type j = 0; j < value_count; ++j )
999 norm[j] = 0.0;
1000 }
1001};
1002
1009template <class Array_t>
1010void norm1( const Array_t& array,
1011 std::vector<typename Array_t::value_type>& norms )
1012{
1013 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
1014 if ( norms.size() !=
1015 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
1016 throw std::runtime_error(
1017 "Cabana::Grid::ArrayOp::norm1: Incorrect vector size" );
1018
1019 for ( auto& n : norms )
1020 n = 0.0;
1021
1023 array.view() );
1024 typename Array_t::execution_space exec_space;
1025 Kokkos::parallel_reduce(
1026 "Cabana::Grid::ArrayOp::norm1",
1027 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
1028 exec_space ),
1029 functor,
1030 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
1031 norms.data(), norms.size() ) );
1032 exec_space.fence( "Cabana::Grid::ArrayOp::norm1 before MPI_Allreduce" );
1033
1034 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
1036 array.layout()->localGrid()->globalGrid().comm() );
1037}
1038
1039//---------------------------------------------------------------------------//
1041template <class ViewType, std::size_t NumSpaceDim>
1043{
1045 static constexpr std::size_t num_space_dim = NumSpaceDim;
1047 typedef typename ViewType::value_type value_type[];
1049 typedef typename ViewType::size_type size_type;
1053 ViewType _view;
1054
1056 Norm2Functor( const ViewType& view )
1057 : value_count( view.extent( NumSpaceDim ) )
1058 , _view( view )
1059 {
1060 }
1061
1063 template <std::size_t NSD = num_space_dim>
1064 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
1065 operator()( const size_type i, const size_type j, const size_type k,
1066 const size_type l, value_type norm ) const
1067 {
1068 norm[l] += _view( i, j, k, l ) * _view( i, j, k, l );
1069 }
1070
1072 template <std::size_t NSD = num_space_dim>
1073 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
1074 operator()( const size_type i, const size_type j, const size_type l,
1075 value_type norm ) const
1076 {
1077 norm[l] += _view( i, j, l ) * _view( i, j, l );
1078 }
1079
1081 KOKKOS_INLINE_FUNCTION
1082 void join( value_type dst, const value_type src ) const
1083 {
1084 for ( size_type j = 0; j < value_count; ++j )
1085 dst[j] += src[j];
1086 }
1087
1089 KOKKOS_INLINE_FUNCTION
1090 void join( volatile value_type dst, const volatile value_type src ) const
1091 {
1092 for ( size_type j = 0; j < value_count; ++j )
1093 dst[j] += src[j];
1094 }
1095
1097 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
1098 {
1099 for ( size_type j = 0; j < value_count; ++j )
1100 norm[j] = 0.0;
1101 }
1102};
1103
1110template <class Array_t>
1111void norm2( const Array_t& array,
1112 std::vector<typename Array_t::value_type>& norms )
1113{
1114 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
1115 if ( norms.size() !=
1116 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
1117 throw std::runtime_error(
1118 "Cabana::Grid::ArrayOp::norm2: Incorrect vector size" );
1119
1120 for ( auto& n : norms )
1121 n = 0.0;
1122
1124 array.view() );
1125 typename Array_t::execution_space exec_space;
1126 Kokkos::parallel_reduce(
1127 "Cabana::Grid::ArrayOp::norm2",
1128 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
1129 exec_space ),
1130 functor,
1131 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
1132 norms.data(), norms.size() ) );
1133 exec_space.fence( "Cabana::Grid::ArrayOp::norm2 before MPI_Allreduce" );
1134
1135 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
1137 array.layout()->localGrid()->globalGrid().comm() );
1138
1139 for ( auto& n : norms )
1140 n = std::sqrt( n );
1141}
1142//---------------------------------------------------------------------------//
1143
1144} // end namespace ArrayOp
1145
1146//---------------------------------------------------------------------------//
1147
1148} // namespace Grid
1149} // namespace Cabana
1150
1151#endif // end CABANA_GRID_ARRAY_HPP
void dot(const Array_t &a, const Array_t &b, std::vector< typename Array_t::value_type > &products)
Compute the dot product of owned space of two arrays.
Definition Cabana_Grid_Array.hpp:802
std::enable_if_t< 3==Array_t::num_space_dim, void > update(Array_t &a, const typename Array_t::value_type alpha, const Array_t &b, const typename Array_t::value_type beta, DecompositionTag tag)
Update two vectors such that a = alpha * a + beta * b. 3D specialization.
Definition Cabana_Grid_Array.hpp:617
std::shared_ptr< Array< Scalar, EntityType, MeshType, Params... > > clone(const Array< Scalar, EntityType, MeshType, Params... > &array)
Clone an array. Do not initialize the clone.
Definition Cabana_Grid_Array.hpp:419
void copy(Array_t &a, const Array_t &b, DecompositionTag tag)
Copy one array into another over the designated decomposition. A <- B.
Definition Cabana_Grid_Array.hpp:575
std::shared_ptr< Array< Scalar, EntityType, MeshType, typename Array< Scalar, EntityType, MeshType, Params... >::subview_layout, typename Array< Scalar, EntityType, MeshType, Params... >::memory_space, typename Array< Scalar, EntityType, MeshType, Params... >::subview_memory_traits > > createSubarray(const Array< Scalar, EntityType, MeshType, Params... > &array, const int dof_min, const int dof_max)
Create a subarray of the given array over the given range of degrees of freedom.
Definition Cabana_Grid_Array.hpp:376
void normInf(const Array_t &array, std::vector< typename Array_t::value_type > &norms)
Calculate the infinity-norm of the owned elements of the array.
Definition Cabana_Grid_Array.hpp:909
std::enable_if_t< 3==Array_t::num_space_dim, void > scale(Array_t &array, const typename Array_t::value_type alpha, DecompositionTag tag)
Scale every element of an array by a scalar value. 3D specialization.
Definition Cabana_Grid_Array.hpp:452
void norm2(const Array_t &array, std::vector< typename Array_t::value_type > &norms)
Calculate the two-norm of the owned elements of the array.
Definition Cabana_Grid_Array.hpp:1111
std::shared_ptr< Array< Scalar, EntityType, MeshType, Params... > > createArray(const std::string &label, const std::shared_ptr< ArrayLayout< EntityType, MeshType > > &layout)
Create an array with the given array layout. Views are constructed over the ghosted index space of th...
Definition Cabana_Grid_Array.hpp:351
void norm1(const Array_t &array, std::vector< typename Array_t::value_type > &norms)
Calculate the one-norm of the owned elements of the array.
Definition Cabana_Grid_Array.hpp:1010
std::shared_ptr< ArrayLayout< EntityType, MeshType > > createArrayLayout(const std::shared_ptr< LocalGrid< MeshType > > &local_grid, const int dofs_per_entity, EntityType)
Create an array layout over the entities of a local grid.
Definition Cabana_Grid_Array.hpp:189
std::shared_ptr< Array_t > cloneCopy(const Array_t &array, DecompositionTag tag)
Clone an array and copy its contents into the clone.
Definition Cabana_Grid_Array.hpp:598
void assign(Array_t &array, const typename Array_t::value_type alpha, DecompositionTag tag)
Assign a scalar value to every element of an array.
Definition Cabana_Grid_Array.hpp:432
Logical grid indexing.
KOKKOS_INLINE_FUNCTION auto createSubview(const ViewType &view, const IndexSpace< 1 > &index_space) -> decltype(Kokkos::subview(view, index_space.range(0)))
Given a view create a subview over the given index space.
Definition Cabana_Grid_IndexSpace.hpp:369
Kokkos::RangePolicy< ExecutionSpace > createExecutionPolicy(const IndexSpace< 1 > &index_space, const ExecutionSpace &)
Create a multi-dimensional execution policy over an index space.
Definition Cabana_Grid_IndexSpace.hpp:175
Kokkos::View< Scalar *, Params... > createView(const std::string &label, const IndexSpace< 1 > &index_space)
Given an index space create a view over the extent of that index space.
Definition Cabana_Grid_IndexSpace.hpp:235
IndexSpace< N+1 > appendDimension(const IndexSpace< N > &index_space, const long size)
Given an N-dimensional index space append an additional dimension with the given size.
Definition Cabana_Grid_IndexSpace.hpp:442
std::shared_ptr< LocalGrid< MeshType > > createLocalGrid(const std::shared_ptr< GlobalGrid< MeshType > > &global_grid, const int halo_cell_width)
Create a local grid.
Definition Cabana_Grid_LocalGrid.hpp:607
Grid type tags.
Entity layout for array data on the local mesh.
Definition Cabana_Grid_Array.hpp:46
std::enable_if_t< 3==NSD, IndexSpace< 4 > > sharedIndexSpace(DecompositionTag decomposition_tag, const int off_i, const int off_j, const int off_k, const int halo_width=-1) const
Definition Cabana_Grid_Array.hpp:125
ArrayLayout(const std::shared_ptr< LocalGrid< MeshType > > &local_grid, const int dofs_per_entity)
Constructor.
Definition Cabana_Grid_Array.hpp:63
MeshType mesh_type
Mesh type.
Definition Cabana_Grid_Array.hpp:52
IndexSpace< num_space_dim+1 > indexSpace(DecompositionTag decomposition_tag, IndexType index_type) const
Definition Cabana_Grid_Array.hpp:83
int dofsPerEntity() const
Get the number of degrees-of-freedom on each grid entity.
Definition Cabana_Grid_Array.hpp:77
IndexSpace< num_space_dim+1 > sharedIndexSpace(DecompositionTag decomposition_tag, const std::array< int, num_space_dim > &off_ijk, const int halo_width=-1) const
Definition Cabana_Grid_Array.hpp:103
std::enable_if_t< 2==NSD, IndexSpace< 3 > > sharedIndexSpace(DecompositionTag decomposition_tag, const int off_i, const int off_j, const int halo_width=-1) const
Definition Cabana_Grid_Array.hpp:145
const std::shared_ptr< LocalGrid< MeshType > > localGrid() const
Get the local grid over which this layout is defined.
Definition Cabana_Grid_Array.hpp:71
static constexpr std::size_t num_space_dim
Definition Cabana_Grid_Array.hpp:55
EntityType entity_type
Entity type.
Definition Cabana_Grid_Array.hpp:49
Array of field data on the local mesh.
Definition Cabana_Grid_Array.hpp:229
std::shared_ptr< array_layout > layout() const
Definition Cabana_Grid_Array.hpp:293
Array(const std::shared_ptr< array_layout > &layout, const view_type &view)
Create an array with the given layout and view. This view should match the array index spaces in size...
Definition Cabana_Grid_Array.hpp:279
typename subview_type::array_layout subview_layout
Subview array layout type.
Definition Cabana_Grid_Array.hpp:310
Array(const std::string &label, const std::shared_ptr< array_layout > &layout)
Create an array with the given layout. Arrays are constructed over the ghosted index space of the lay...
Definition Cabana_Grid_Array.hpp:265
typename subview_type::memory_traits subview_memory_traits
Subview memory traits.
Definition Cabana_Grid_Array.hpp:312
Scalar value_type
Value type.
Definition Cabana_Grid_Array.hpp:232
ArrayLayout< entity_type, mesh_type > array_layout
Array layout type.
Definition Cabana_Grid_Array.hpp:244
MeshType mesh_type
Mesh type.
Definition Cabana_Grid_Array.hpp:238
std::conditional_t< 3==num_space_dim, Kokkos::View< value_type ****, Params... >, std::conditional_t< 2==num_space_dim, Kokkos::View< value_type ***, Params... >, void > > view_type
View type.
Definition Cabana_Grid_Array.hpp:247
decltype(createSubview( _data, _layout->indexSpace(Ghost(), Local()))) subview_type
Subview type.
Definition Cabana_Grid_Array.hpp:307
typename memory_space::execution_space execution_space
Default execution space.
Definition Cabana_Grid_Array.hpp:257
EntityType entity_type
Entity type.
Definition Cabana_Grid_Array.hpp:235
Array< Scalar, EntityType, MeshType, subview_layout, memory_space, subview_memory_traits > subarray_type
Subarray type.
Definition Cabana_Grid_Array.hpp:314
typename view_type::memory_space memory_space
Memory space.
Definition Cabana_Grid_Array.hpp:253
Global logical grid.
Definition Cabana_Grid_GlobalGrid.hpp:39
Structured index space.
Definition Cabana_Grid_IndexSpace.hpp:37
Local logical grid.
Definition Cabana_Grid_LocalGrid.hpp:39
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
Dot product functor.
Definition Cabana_Grid_Array.hpp:729
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:771
ViewType _a
The first array in the dot product.
Definition Cabana_Grid_Array.hpp:739
KOKKOS_INLINE_FUNCTION std::enable_if_t< 3==NSD, void > operator()(const size_type i, const size_type j, const size_type k, const size_type l, value_type sum) const
3d dot product operation.
Definition Cabana_Grid_Array.hpp:754
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:735
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:779
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:731
KOKKOS_INLINE_FUNCTION void init(value_type sum) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:786
KOKKOS_INLINE_FUNCTION std::enable_if_t< 2==NSD, void > operator()(const size_type i, const size_type j, const size_type l, value_type sum) const
2d dot product operation.
Definition Cabana_Grid_Array.hpp:763
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:733
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:737
ViewType _b
The second array in the dot product.
Definition Cabana_Grid_Array.hpp:741
DotFunctor(const ViewType &a, const ViewType &b)
Constructor.
Definition Cabana_Grid_Array.hpp:744
One norm functor.
Definition Cabana_Grid_Array.hpp:942
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:944
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:989
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:948
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:981
KOKKOS_INLINE_FUNCTION std::enable_if_t< 2==NSD, void > operator()(const size_type i, const size_type j, const size_type l, value_type norm) const
2d one norm operation.
Definition Cabana_Grid_Array.hpp:973
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:946
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:996
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:950
KOKKOS_INLINE_FUNCTION std::enable_if_t< 3==NSD, void > operator()(const size_type i, const size_type j, const size_type k, const size_type l, value_type norm) const
3d one norm operation.
Definition Cabana_Grid_Array.hpp:964
Norm1Functor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:955
ViewType _view
Array for the one norm.
Definition Cabana_Grid_Array.hpp:952
Two norm functor.
Definition Cabana_Grid_Array.hpp:1043
ViewType _view
Array for the two norm.
Definition Cabana_Grid_Array.hpp:1053
KOKKOS_INLINE_FUNCTION std::enable_if_t< 2==NSD, void > operator()(const size_type i, const size_type j, const size_type l, value_type norm) const
2d two norm operation.
Definition Cabana_Grid_Array.hpp:1074
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:1049
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:1082
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:1097
KOKKOS_INLINE_FUNCTION std::enable_if_t< 3==NSD, void > operator()(const size_type i, const size_type j, const size_type k, const size_type l, value_type norm) const
3d two norm operation.
Definition Cabana_Grid_Array.hpp:1065
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:1051
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:1047
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:1090
Norm2Functor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:1056
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:1045
Infinity norm functor.
Definition Cabana_Grid_Array.hpp:835
KOKKOS_INLINE_FUNCTION std::enable_if_t< 2==NSD, void > operator()(const size_type i, const size_type j, const size_type l, value_type norm) const
2d infinity norm operation.
Definition Cabana_Grid_Array.hpp:868
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:839
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:843
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:895
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:837
NormInfFunctor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:848
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:841
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:887
ViewType _view
Array for the infinity norm.
Definition Cabana_Grid_Array.hpp:845
KOKKOS_INLINE_FUNCTION std::enable_if_t< 3==NSD, void > operator()(const size_type i, const size_type j, const size_type k, const size_type l, value_type norm) const
3d infinity norm operation.
Definition Cabana_Grid_Array.hpp:857
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:878
Ghosted decomposition tag.
Definition Cabana_Grid_Types.hpp:197
Local index tag.
Definition Cabana_Grid_Types.hpp:208
Definition Cabana_Grid_MpiTraits.hpp:32
Owned decomposition tag.
Definition Cabana_Grid_Types.hpp:190
Array static type checker.
Definition Cabana_Grid_Array.hpp:160
Definition Cabana_Grid_Array.hpp:324