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 "Layout and view dimensions do not match" );
288 }
289
291 std::shared_ptr<array_layout> layout() const { return _layout; }
292
294 view_type view() const { return _data; }
295
297 std::string label() const { return _data.label(); }
298
299 private:
300 std::shared_ptr<array_layout> _layout;
301 view_type _data;
302
303 public:
305 using subview_type = decltype( createSubview(
306 _data, _layout->indexSpace( Ghost(), Local() ) ) );
308 using subview_layout = typename subview_type::array_layout;
310 using subview_memory_traits = typename subview_type::memory_traits;
312 using subarray_type = Array<Scalar, EntityType, MeshType, subview_layout,
314};
315
316//---------------------------------------------------------------------------//
317// Static type checker.
318//---------------------------------------------------------------------------//
319// Static type checker.
320template <class>
321struct is_array : public std::false_type
322{
323};
324
325template <class Scalar, class EntityType, class MeshType, class... Params>
326struct is_array<Array<Scalar, EntityType, MeshType, Params...>>
327 : public std::true_type
328{
329};
330
331template <class Scalar, class EntityType, class MeshType, class... Params>
332struct is_array<const Array<Scalar, EntityType, MeshType, Params...>>
333 : public std::true_type
334{
335};
336
337//---------------------------------------------------------------------------//
338// Array creation.
339//---------------------------------------------------------------------------//
347template <class Scalar, class... Params, class EntityType, class MeshType>
348std::shared_ptr<Array<Scalar, EntityType, MeshType, Params...>>
349createArray( const std::string& label,
350 const std::shared_ptr<ArrayLayout<EntityType, MeshType>>& layout )
351{
352 return std::make_shared<Array<Scalar, EntityType, MeshType, Params...>>(
353 label, layout );
354}
355
356//---------------------------------------------------------------------------//
357// Subarray creation.
358//---------------------------------------------------------------------------//
367template <class Scalar, class EntityType, class MeshType, class... Params>
368std::shared_ptr<Array<
369 Scalar, EntityType, MeshType,
370 typename Array<Scalar, EntityType, MeshType, Params...>::subview_layout,
371 typename Array<Scalar, EntityType, MeshType, Params...>::memory_space,
372 typename Array<Scalar, EntityType, MeshType,
373 Params...>::subview_memory_traits>>
375 const int dof_min, const int dof_max )
376{
377 if ( dof_min < 0 || dof_max > array.layout()->dofsPerEntity() )
378 throw std::logic_error( "Subarray dimensions out of bounds" );
379
380 auto space = array.layout()->indexSpace( Ghost(), Local() );
381 std::array<long, MeshType::num_space_dim + 1> min;
382 std::array<long, MeshType::num_space_dim + 1> max;
383 for ( std::size_t d = 0; d < MeshType::num_space_dim; ++d )
384 {
385 min[d] = space.min( d );
386 max[d] = space.max( d );
387 }
388 min.back() = dof_min;
389 max.back() = dof_max;
390 IndexSpace<MeshType::num_space_dim + 1> sub_space( min, max );
391 auto sub_view = createSubview( array.view(), sub_space );
392 auto sub_layout = createArrayLayout( array.layout()->localGrid(),
393 dof_max - dof_min, EntityType() );
394 return std::make_shared<Array<
395 Scalar, EntityType, MeshType,
396 typename Array<Scalar, EntityType, MeshType, Params...>::subview_layout,
397 typename Array<Scalar, EntityType, MeshType, Params...>::memory_space,
398 typename Array<Scalar, EntityType, MeshType,
399 Params...>::subview_memory_traits>>( sub_layout,
400 sub_view );
401}
402
403//---------------------------------------------------------------------------//
404// Array operations.
405//---------------------------------------------------------------------------//
406namespace ArrayOp
407{
408//---------------------------------------------------------------------------//
413template <class Scalar, class... Params, class EntityType, class MeshType>
414std::shared_ptr<Array<Scalar, EntityType, MeshType, Params...>>
416{
417 return createArray<Scalar, Params...>( array.label(), array.layout() );
418}
419
420//---------------------------------------------------------------------------//
427template <class Array_t, class DecompositionTag>
428void assign( Array_t& array, const typename Array_t::value_type alpha,
429 DecompositionTag tag )
430{
431 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
432 auto subview = createSubview( array.view(),
433 array.layout()->indexSpace( tag, Local() ) );
434 Kokkos::deep_copy( subview, alpha );
435}
436
437//---------------------------------------------------------------------------//
444template <class Array_t, class DecompositionTag>
445std::enable_if_t<3 == Array_t::num_space_dim, void>
446scale( Array_t& array, const typename Array_t::value_type alpha,
447 DecompositionTag tag )
448{
449 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
450 auto view = array.view();
451 Kokkos::parallel_for(
452 "ArrayOp::scale",
453 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
454 typename Array_t::execution_space() ),
455 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
456 view( i, j, k, l ) *= alpha;
457 } );
458}
459
466template <class Array_t, class DecompositionTag>
467std::enable_if_t<2 == Array_t::num_space_dim, void>
468scale( Array_t& array, const typename Array_t::value_type alpha,
469 DecompositionTag tag )
470{
471 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
472 auto view = array.view();
473 Kokkos::parallel_for(
474 "ArrayOp::scale",
475 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
476 typename Array_t::execution_space() ),
477 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
478 view( i, j, l ) *= alpha;
479 } );
480}
481
482//---------------------------------------------------------------------------//
490template <class Array_t, class DecompositionTag>
491std::enable_if_t<3 == Array_t::num_space_dim, void>
492scale( Array_t& array, const std::vector<typename Array_t::value_type>& alpha,
493 DecompositionTag tag )
494{
495 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
496 if ( alpha.size() !=
497 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
498 throw std::runtime_error( "Incorrect vector size" );
499
500 Kokkos::View<const typename Array_t::value_type*, Kokkos::HostSpace,
501 Kokkos::MemoryUnmanaged>
502 alpha_view_host( alpha.data(), alpha.size() );
503 auto alpha_view = Kokkos::create_mirror_view_and_copy(
504 typename Array_t::memory_space(), alpha_view_host );
505
506 auto array_view = array.view();
507 Kokkos::parallel_for(
508 "ArrayOp::scale",
509 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
510 typename Array_t::execution_space() ),
511 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
512 array_view( i, j, k, l ) *= alpha_view( l );
513 } );
514}
515
523template <class Array_t, class DecompositionTag>
524std::enable_if_t<2 == Array_t::num_space_dim, void>
525scale( Array_t& array, const std::vector<typename Array_t::value_type>& alpha,
526 DecompositionTag tag )
527{
528 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
529 if ( alpha.size() !=
530 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
531 throw std::runtime_error( "Incorrect vector size" );
532
533 Kokkos::View<const typename Array_t::value_type*, Kokkos::HostSpace,
534 Kokkos::MemoryUnmanaged>
535 alpha_view_host( alpha.data(), alpha.size() );
536 auto alpha_view = Kokkos::create_mirror_view_and_copy(
537 typename Array_t::memory_space(), alpha_view_host );
538
539 auto array_view = array.view();
540 Kokkos::parallel_for(
541 "ArrayOp::scale",
542 createExecutionPolicy( array.layout()->indexSpace( tag, Local() ),
543 typename Array_t::execution_space() ),
544 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
545 array_view( i, j, l ) *= alpha_view( l );
546 } );
547}
548
549//---------------------------------------------------------------------------//
556template <class Array_t, class DecompositionTag>
557void copy( Array_t& a, const Array_t& b, DecompositionTag tag )
558{
559 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
560 auto a_space = a.layout()->indexSpace( tag, Local() );
561 auto b_space = b.layout()->indexSpace( tag, Local() );
562 if ( a_space != b_space )
563 throw std::logic_error( "Incompatible index spaces" );
564 auto subview_a = createSubview( a.view(), a_space );
565 auto subview_b = createSubview( b.view(), b_space );
566 Kokkos::deep_copy( subview_a, subview_b );
567}
568
569//---------------------------------------------------------------------------//
575template <class Array_t, class DecompositionTag>
576std::shared_ptr<Array_t> cloneCopy( const Array_t& array, DecompositionTag tag )
577{
578 auto cln = clone( array );
579 copy( *cln, array, tag );
580 return cln;
581}
582
583//---------------------------------------------------------------------------//
593template <class Array_t, class DecompositionTag>
594std::enable_if_t<3 == Array_t::num_space_dim, void>
595update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
596 const typename Array_t::value_type beta, DecompositionTag tag )
597{
598 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
599 auto a_view = a.view();
600 auto b_view = b.view();
601 Kokkos::parallel_for(
602 "ArrayOp::update",
603 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
604 typename Array_t::execution_space() ),
605 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
606 a_view( i, j, k, l ) =
607 alpha * a_view( i, j, k, l ) + beta * b_view( i, j, k, l );
608 } );
609}
610
620template <class Array_t, class DecompositionTag>
621std::enable_if_t<2 == Array_t::num_space_dim, void>
622update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
623 const typename Array_t::value_type beta, DecompositionTag tag )
624{
625 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
626 auto a_view = a.view();
627 auto b_view = b.view();
628 Kokkos::parallel_for(
629 "ArrayOp::update",
630 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
631 typename Array_t::execution_space() ),
632 KOKKOS_LAMBDA( const long i, const long j, const long l ) {
633 a_view( i, j, l ) =
634 alpha * a_view( i, j, l ) + beta * b_view( i, j, l );
635 } );
636}
637
638//---------------------------------------------------------------------------//
650template <class Array_t, class DecompositionTag>
651std::enable_if_t<3 == Array_t::num_space_dim, void>
652update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
653 const typename Array_t::value_type beta, const Array_t& c,
654 const typename Array_t::value_type gamma, DecompositionTag tag )
655{
656 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
657 auto a_view = a.view();
658 auto b_view = b.view();
659 auto c_view = c.view();
660 Kokkos::parallel_for(
661 "ArrayOp::update",
662 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
663 typename Array_t::execution_space() ),
664 KOKKOS_LAMBDA( const int i, const int j, const int k, const int l ) {
665 a_view( i, j, k, l ) = alpha * a_view( i, j, k, l ) +
666 beta * b_view( i, j, k, l ) +
667 gamma * c_view( i, j, k, l );
668 } );
669}
670
682template <class Array_t, class DecompositionTag>
683std::enable_if_t<2 == Array_t::num_space_dim, void>
684update( Array_t& a, const typename Array_t::value_type alpha, const Array_t& b,
685 const typename Array_t::value_type beta, const Array_t& c,
686 const typename Array_t::value_type gamma, DecompositionTag tag )
687{
688 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
689 auto a_view = a.view();
690 auto b_view = b.view();
691 auto c_view = c.view();
692 Kokkos::parallel_for(
693 "ArrayOp::update",
694 createExecutionPolicy( a.layout()->indexSpace( tag, Local() ),
695 typename Array_t::execution_space() ),
696 KOKKOS_LAMBDA( const int i, const int j, const int l ) {
697 a_view( i, j, l ) = alpha * a_view( i, j, l ) +
698 beta * b_view( i, j, l ) +
699 gamma * c_view( i, j, l );
700 } );
701}
702
703//---------------------------------------------------------------------------//
705template <class ViewType, std::size_t NumSpaceDim>
707{
709 static constexpr std::size_t num_space_dim = NumSpaceDim;
711 typedef typename ViewType::value_type value_type[];
713 typedef typename ViewType::size_type size_type;
717 ViewType _a;
719 ViewType _b;
720
722 DotFunctor( const ViewType& a, const ViewType& b )
723 : value_count( a.extent( NumSpaceDim ) )
724 , _a( a )
725 , _b( b )
726 {
727 }
728
730 template <std::size_t NSD = num_space_dim>
731 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
732 operator()( const size_type i, const size_type j, const size_type k,
733 const size_type l, value_type sum ) const
734 {
735 sum[l] += _a( i, j, k, l ) * _b( i, j, k, l );
736 }
737
739 template <std::size_t NSD = num_space_dim>
740 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
741 operator()( const size_type i, const size_type j, const size_type l,
742 value_type sum ) const
743 {
744 sum[l] += _a( i, j, l ) * _b( i, j, l );
745 }
746
748 KOKKOS_INLINE_FUNCTION
749 void join( value_type dst, const value_type src ) const
750 {
751 for ( size_type j = 0; j < value_count; ++j )
752 dst[j] += src[j];
753 }
754
756 KOKKOS_INLINE_FUNCTION
757 void join( volatile value_type dst, const volatile value_type src ) const
758 {
759 for ( size_type j = 0; j < value_count; ++j )
760 dst[j] += src[j];
761 }
762
764 KOKKOS_INLINE_FUNCTION void init( value_type sum ) const
765 {
766 for ( size_type j = 0; j < value_count; ++j )
767 sum[j] = 0.0;
768 }
769};
770
779template <class Array_t>
780void dot( const Array_t& a, const Array_t& b,
781 std::vector<typename Array_t::value_type>& products )
782{
783 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
784 if ( products.size() !=
785 static_cast<unsigned>( a.layout()->dofsPerEntity() ) )
786 throw std::runtime_error( "Incorrect vector size" );
787
788 for ( auto& p : products )
789 p = 0.0;
790
792 a.view(), b.view() );
793 typename Array_t::execution_space exec_space;
794 Kokkos::parallel_reduce(
795 "ArrayOp::dot",
796 createExecutionPolicy( a.layout()->indexSpace( Own(), Local() ),
797 exec_space ),
798 functor,
799 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
800 products.data(), products.size() ) );
801 exec_space.fence( "ArrayOp::dot before MPI_Allreduce" );
802
803 MPI_Allreduce( MPI_IN_PLACE, products.data(), products.size(),
805 a.layout()->localGrid()->globalGrid().comm() );
806}
807
808//---------------------------------------------------------------------------//
810template <class ViewType, std::size_t NumSpaceDim>
812{
814 static constexpr std::size_t num_space_dim = NumSpaceDim;
816 typedef typename ViewType::value_type value_type[];
818 typedef typename ViewType::size_type size_type;
822 ViewType _view;
823
825 NormInfFunctor( const ViewType& view )
826 : value_count( view.extent( NumSpaceDim ) )
827 , _view( view )
828 {
829 }
830
832 template <std::size_t NSD = num_space_dim>
833 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
834 operator()( const size_type i, const size_type j, const size_type k,
835 const size_type l, value_type norm ) const
836 {
837 auto v_abs = fabs( _view( i, j, k, l ) );
838 if ( v_abs > norm[l] )
839 norm[l] = v_abs;
840 }
841
843 template <std::size_t NSD = num_space_dim>
844 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
845 operator()( const size_type i, const size_type j, const size_type l,
846 value_type norm ) const
847 {
848 auto v_abs = fabs( _view( i, j, l ) );
849 if ( v_abs > norm[l] )
850 norm[l] = v_abs;
851 }
852
854 KOKKOS_INLINE_FUNCTION
855 void join( value_type dst, const value_type src ) const
856 {
857 for ( size_type j = 0; j < value_count; ++j )
858 if ( src[j] > dst[j] )
859 dst[j] = src[j];
860 }
861
863 KOKKOS_INLINE_FUNCTION
864 void join( volatile value_type dst, const volatile value_type src ) const
865 {
866 for ( size_type j = 0; j < value_count; ++j )
867 if ( src[j] > dst[j] )
868 dst[j] = src[j];
869 }
870
872 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
873 {
874 for ( size_type j = 0; j < value_count; ++j )
875 norm[j] = 0.0;
876 }
877};
878
885template <class Array_t>
886void normInf( const Array_t& array,
887 std::vector<typename Array_t::value_type>& norms )
888{
889 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
890 if ( norms.size() !=
891 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
892 throw std::runtime_error( "Incorrect vector size" );
893
894 for ( auto& n : norms )
895 n = 0.0;
896
898 array.view() );
899 typename Array_t::execution_space exec_space;
900 Kokkos::parallel_reduce(
901 "ArrayOp::normInf",
902 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
903 exec_space ),
904 functor,
905 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
906 norms.data(), norms.size() ) );
907 exec_space.fence( "ArrayOp::normInf before MPI_Allreduce" );
908
909 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
911 array.layout()->localGrid()->globalGrid().comm() );
912}
913
914//---------------------------------------------------------------------------//
916template <class ViewType, std::size_t NumSpaceDim>
918{
920 static constexpr std::size_t num_space_dim = NumSpaceDim;
922 typedef typename ViewType::value_type value_type[];
924 typedef typename ViewType::size_type size_type;
928 ViewType _view;
929
931 Norm1Functor( const ViewType& view )
932 : value_count( view.extent( NumSpaceDim ) )
933 , _view( view )
934 {
935 }
936
938 template <std::size_t NSD = num_space_dim>
939 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
940 operator()( const size_type i, const size_type j, const size_type k,
941 const size_type l, value_type norm ) const
942 {
943 norm[l] += fabs( _view( i, j, k, l ) );
944 }
945
947 template <std::size_t NSD = num_space_dim>
948 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
949 operator()( const size_type i, const size_type j, const size_type l,
950 value_type norm ) const
951 {
952 norm[l] += fabs( _view( i, j, l ) );
953 }
954
956 KOKKOS_INLINE_FUNCTION
957 void join( value_type dst, const value_type src ) const
958 {
959 for ( size_type j = 0; j < value_count; ++j )
960 dst[j] += src[j];
961 }
962
964 KOKKOS_INLINE_FUNCTION
965 void join( volatile value_type dst, const volatile value_type src ) const
966 {
967 for ( size_type j = 0; j < value_count; ++j )
968 dst[j] += src[j];
969 }
970
972 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
973 {
974 for ( size_type j = 0; j < value_count; ++j )
975 norm[j] = 0.0;
976 }
977};
978
985template <class Array_t>
986void norm1( const Array_t& array,
987 std::vector<typename Array_t::value_type>& norms )
988{
989 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
990 if ( norms.size() !=
991 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
992 throw std::runtime_error( "Incorrect vector size" );
993
994 for ( auto& n : norms )
995 n = 0.0;
996
998 array.view() );
999 typename Array_t::execution_space exec_space;
1000 Kokkos::parallel_reduce(
1001 "ArrayOp::norm1",
1002 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
1003 exec_space ),
1004 functor,
1005 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
1006 norms.data(), norms.size() ) );
1007 exec_space.fence( "ArrayOp::norm1 before MPI_Allreduce" );
1008
1009 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
1011 array.layout()->localGrid()->globalGrid().comm() );
1012}
1013
1014//---------------------------------------------------------------------------//
1016template <class ViewType, std::size_t NumSpaceDim>
1018{
1020 static constexpr std::size_t num_space_dim = NumSpaceDim;
1022 typedef typename ViewType::value_type value_type[];
1024 typedef typename ViewType::size_type size_type;
1028 ViewType _view;
1029
1031 Norm2Functor( const ViewType& view )
1032 : value_count( view.extent( NumSpaceDim ) )
1033 , _view( view )
1034 {
1035 }
1036
1038 template <std::size_t NSD = num_space_dim>
1039 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
1040 operator()( const size_type i, const size_type j, const size_type k,
1041 const size_type l, value_type norm ) const
1042 {
1043 norm[l] += _view( i, j, k, l ) * _view( i, j, k, l );
1044 }
1045
1047 template <std::size_t NSD = num_space_dim>
1048 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
1049 operator()( const size_type i, const size_type j, const size_type l,
1050 value_type norm ) const
1051 {
1052 norm[l] += _view( i, j, l ) * _view( i, j, l );
1053 }
1054
1056 KOKKOS_INLINE_FUNCTION
1057 void join( value_type dst, const value_type src ) const
1058 {
1059 for ( size_type j = 0; j < value_count; ++j )
1060 dst[j] += src[j];
1061 }
1062
1064 KOKKOS_INLINE_FUNCTION
1065 void join( volatile value_type dst, const volatile value_type src ) const
1066 {
1067 for ( size_type j = 0; j < value_count; ++j )
1068 dst[j] += src[j];
1069 }
1070
1072 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
1073 {
1074 for ( size_type j = 0; j < value_count; ++j )
1075 norm[j] = 0.0;
1076 }
1077};
1078
1085template <class Array_t>
1086void norm2( const Array_t& array,
1087 std::vector<typename Array_t::value_type>& norms )
1088{
1089 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
1090 if ( norms.size() !=
1091 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
1092 throw std::runtime_error( "Incorrect vector size" );
1093
1094 for ( auto& n : norms )
1095 n = 0.0;
1096
1098 array.view() );
1099 typename Array_t::execution_space exec_space;
1100 Kokkos::parallel_reduce(
1101 "ArrayOp::norm2",
1102 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
1103 exec_space ),
1104 functor,
1105 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
1106 norms.data(), norms.size() ) );
1107 exec_space.fence( "ArrayOp::norm2 before MPI_Allreduce" );
1108
1109 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
1111 array.layout()->localGrid()->globalGrid().comm() );
1112
1113 for ( auto& n : norms )
1114 n = std::sqrt( n );
1115}
1116//---------------------------------------------------------------------------//
1117
1118} // end namespace ArrayOp
1119
1120//---------------------------------------------------------------------------//
1121
1122} // namespace Grid
1123} // namespace Cabana
1124
1125#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:780
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:595
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:415
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:557
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:374
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:886
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:446
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:1086
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:349
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:986
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:576
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:428
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:291
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:308
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:310
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:305
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:312
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:707
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:749
ViewType _a
The first array in the dot product.
Definition Cabana_Grid_Array.hpp:717
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:732
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:713
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:757
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:709
KOKKOS_INLINE_FUNCTION void init(value_type sum) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:764
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:741
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:711
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:715
ViewType _b
The second array in the dot product.
Definition Cabana_Grid_Array.hpp:719
DotFunctor(const ViewType &a, const ViewType &b)
Constructor.
Definition Cabana_Grid_Array.hpp:722
One norm functor.
Definition Cabana_Grid_Array.hpp:918
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:920
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:965
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:924
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:957
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:949
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:922
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:972
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:926
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:940
Norm1Functor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:931
ViewType _view
Array for the one norm.
Definition Cabana_Grid_Array.hpp:928
Two norm functor.
Definition Cabana_Grid_Array.hpp:1018
ViewType _view
Array for the two norm.
Definition Cabana_Grid_Array.hpp:1028
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:1049
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:1024
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:1057
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:1072
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:1040
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:1026
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:1022
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:1065
Norm2Functor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:1031
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:1020
Infinity norm functor.
Definition Cabana_Grid_Array.hpp:812
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:845
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:816
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:820
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:872
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:814
NormInfFunctor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:825
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:818
KOKKOS_INLINE_FUNCTION void join(volatile value_type dst, const volatile value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:864
ViewType _view
Array for the infinity norm.
Definition Cabana_Grid_Array.hpp:822
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:834
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:855
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:322