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;
254 static_assert( Kokkos::is_memory_space<memory_space>() );
255
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 void init( value_type sum ) const
779 {
780 for ( size_type j = 0; j < value_count; ++j )
781 sum[j] = 0.0;
782 }
783};
784
793template <class Array_t>
794void dot( const Array_t& a, const Array_t& b,
795 std::vector<typename Array_t::value_type>& products )
796{
797 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
798 if ( products.size() !=
799 static_cast<unsigned>( a.layout()->dofsPerEntity() ) )
800 throw std::runtime_error(
801 "Cabana::Grid::ArrayOp::dot: Incorrect vector size" );
802
803 for ( auto& p : products )
804 p = 0.0;
805
807 a.view(), b.view() );
808 typename Array_t::execution_space exec_space;
809 Kokkos::parallel_reduce(
810 "Cabana::Grid::ArrayOp::dot",
811 createExecutionPolicy( a.layout()->indexSpace( Own(), Local() ),
812 exec_space ),
813 functor,
814 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
815 products.data(), products.size() ) );
816 exec_space.fence( "Cabana::Grid::ArrayOp::dot before MPI_Allreduce" );
817
818 MPI_Allreduce( MPI_IN_PLACE, products.data(), products.size(),
820 a.layout()->localGrid()->globalGrid().comm() );
821}
822
823//---------------------------------------------------------------------------//
825template <class ViewType, std::size_t NumSpaceDim>
827{
829 static constexpr std::size_t num_space_dim = NumSpaceDim;
831 typedef typename ViewType::value_type value_type[];
833 typedef typename ViewType::size_type size_type;
837 ViewType _view;
838
840 NormInfFunctor( const ViewType& view )
841 : value_count( view.extent( NumSpaceDim ) )
842 , _view( view )
843 {
844 }
845
847 template <std::size_t NSD = num_space_dim>
848 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
849 operator()( const size_type i, const size_type j, const size_type k,
850 const size_type l, value_type norm ) const
851 {
852 auto v_abs = fabs( _view( i, j, k, l ) );
853 if ( v_abs > norm[l] )
854 norm[l] = v_abs;
855 }
856
858 template <std::size_t NSD = num_space_dim>
859 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
860 operator()( const size_type i, const size_type j, const size_type l,
861 value_type norm ) const
862 {
863 auto v_abs = fabs( _view( i, j, l ) );
864 if ( v_abs > norm[l] )
865 norm[l] = v_abs;
866 }
867
869 KOKKOS_INLINE_FUNCTION
870 void join( value_type dst, const value_type src ) const
871 {
872 for ( size_type j = 0; j < value_count; ++j )
873 if ( src[j] > dst[j] )
874 dst[j] = src[j];
875 }
876
878 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
879 {
880 for ( size_type j = 0; j < value_count; ++j )
881 norm[j] = 0.0;
882 }
883};
884
891template <class Array_t>
892void normInf( const Array_t& array,
893 std::vector<typename Array_t::value_type>& norms )
894{
895 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
896 if ( norms.size() !=
897 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
898 throw std::runtime_error(
899 "Cabana::Grid::ArrayOp::normInf: Incorrect vector size" );
900
901 for ( auto& n : norms )
902 n = 0.0;
903
905 array.view() );
906 typename Array_t::execution_space exec_space;
907 Kokkos::parallel_reduce(
908 "Cabana::Grid::ArrayOp::normInf",
909 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
910 exec_space ),
911 functor,
912 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
913 norms.data(), norms.size() ) );
914 exec_space.fence( "ArrayOp::normInf before MPI_Allreduce" );
915
916 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
918 array.layout()->localGrid()->globalGrid().comm() );
919}
920
921//---------------------------------------------------------------------------//
923template <class ViewType, std::size_t NumSpaceDim>
925{
927 static constexpr std::size_t num_space_dim = NumSpaceDim;
929 typedef typename ViewType::value_type value_type[];
931 typedef typename ViewType::size_type size_type;
935 ViewType _view;
936
938 Norm1Functor( const ViewType& view )
939 : value_count( view.extent( NumSpaceDim ) )
940 , _view( view )
941 {
942 }
943
945 template <std::size_t NSD = num_space_dim>
946 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
947 operator()( const size_type i, const size_type j, const size_type k,
948 const size_type l, value_type norm ) const
949 {
950 norm[l] += fabs( _view( i, j, k, l ) );
951 }
952
954 template <std::size_t NSD = num_space_dim>
955 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
956 operator()( const size_type i, const size_type j, const size_type l,
957 value_type norm ) const
958 {
959 norm[l] += fabs( _view( i, j, l ) );
960 }
961
963 KOKKOS_INLINE_FUNCTION
964 void join( value_type dst, const value_type src ) const
965 {
966 for ( size_type j = 0; j < value_count; ++j )
967 dst[j] += src[j];
968 }
969
971 KOKKOS_INLINE_FUNCTION void init( value_type norm ) const
972 {
973 for ( size_type j = 0; j < value_count; ++j )
974 norm[j] = 0.0;
975 }
976};
977
984template <class Array_t>
985void norm1( const Array_t& array,
986 std::vector<typename Array_t::value_type>& norms )
987{
988 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
989 if ( norms.size() !=
990 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
991 throw std::runtime_error(
992 "Cabana::Grid::ArrayOp::norm1: 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 "Cabana::Grid::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( "Cabana::Grid::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 void init( value_type norm ) const
1065 {
1066 for ( size_type j = 0; j < value_count; ++j )
1067 norm[j] = 0.0;
1068 }
1069};
1070
1077template <class Array_t>
1078void norm2( const Array_t& array,
1079 std::vector<typename Array_t::value_type>& norms )
1080{
1081 static_assert( is_array<Array_t>::value, "Cabana::Grid::Array required" );
1082 if ( norms.size() !=
1083 static_cast<unsigned>( array.layout()->dofsPerEntity() ) )
1084 throw std::runtime_error(
1085 "Cabana::Grid::ArrayOp::norm2: Incorrect vector size" );
1086
1087 for ( auto& n : norms )
1088 n = 0.0;
1089
1091 array.view() );
1092 typename Array_t::execution_space exec_space;
1093 Kokkos::parallel_reduce(
1094 "Cabana::Grid::ArrayOp::norm2",
1095 createExecutionPolicy( array.layout()->indexSpace( Own(), Local() ),
1096 exec_space ),
1097 functor,
1098 Kokkos::View<typename Array_t::value_type*, Kokkos::HostSpace>(
1099 norms.data(), norms.size() ) );
1100 exec_space.fence( "Cabana::Grid::ArrayOp::norm2 before MPI_Allreduce" );
1101
1102 MPI_Allreduce( MPI_IN_PLACE, norms.data(), norms.size(),
1104 array.layout()->localGrid()->globalGrid().comm() );
1105
1106 for ( auto& n : norms )
1107 n = std::sqrt( n );
1108}
1109//---------------------------------------------------------------------------//
1110
1111} // end namespace ArrayOp
1112
1113//---------------------------------------------------------------------------//
1114
1115} // namespace Grid
1116} // namespace Cabana
1117
1118#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:794
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:892
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:1078
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:985
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:371
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:237
Kokkos::RangePolicy< ExecutionSpace > createExecutionPolicy(const IndexSpace< 1 > &index_space, const ExecutionSpace &exec_space)
Create a multi-dimensional execution policy over an index space.
Definition Cabana_Grid_IndexSpace.hpp:175
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:444
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
Kokkos 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
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:778
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:925
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:927
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:931
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:964
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:956
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:929
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:971
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:933
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:947
Norm1Functor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:938
ViewType _view
Array for the one norm.
Definition Cabana_Grid_Array.hpp:935
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:1064
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
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:827
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:860
ViewType::value_type value_type[]
Value type.
Definition Cabana_Grid_Array.hpp:831
size_type value_count
Size of the array.
Definition Cabana_Grid_Array.hpp:835
KOKKOS_INLINE_FUNCTION void init(value_type norm) const
Zero initialization.
Definition Cabana_Grid_Array.hpp:878
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Array.hpp:829
NormInfFunctor(const ViewType &view)
Constructor.
Definition Cabana_Grid_Array.hpp:840
ViewType::size_type size_type
Size type.
Definition Cabana_Grid_Array.hpp:833
ViewType _view
Array for the infinity norm.
Definition Cabana_Grid_Array.hpp:837
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:849
KOKKOS_INLINE_FUNCTION void join(value_type dst, const value_type src) const
Join operation.
Definition Cabana_Grid_Array.hpp:870
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