From 55f66a0702d65dac27b28c481e810879c227050d Mon Sep 17 00:00:00 2001 From: Slavko Brdar Date: Thu, 7 Sep 2023 17:59:53 +0200 Subject: [PATCH] 1) turn fypp to F90; 2) add a Fortran unit test for MultiField --- src/atlas/field/FieldSet.cc | 4 +- src/atlas/field/detail/MultiFieldInterface.cc | 19 ++- src/atlas/field/detail/MultiFieldInterface.h | 3 +- src/atlas_f/CMakeLists.txt | 2 +- src/atlas_f/field/atlas_MultiField_module.F90 | 125 ++++++++++++++++++ src/tests/field/fctest_multifield_ifs.F90 | 15 ++- src/tests/field/test_multifield_ifs.cc | 8 ++ 7 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 src/atlas_f/field/atlas_MultiField_module.F90 diff --git a/src/atlas/field/FieldSet.cc b/src/atlas/field/FieldSet.cc index ecf53e0cc..f3d7a8bfb 100644 --- a/src/atlas/field/FieldSet.cc +++ b/src/atlas/field/FieldSet.cc @@ -70,8 +70,8 @@ Field FieldSetImpl::add(const Field& field) { } void FieldSetImpl::add_fieldset(const FieldSet& fieldset) { - for( auto& field : fieldset) { - add(field); + for( auto field : fieldset) { + this->add(field); } } diff --git a/src/atlas/field/detail/MultiFieldInterface.cc b/src/atlas/field/detail/MultiFieldInterface.cc index 8e7b5daae..e9abd6a0a 100644 --- a/src/atlas/field/detail/MultiFieldInterface.cc +++ b/src/atlas/field/detail/MultiFieldInterface.cc @@ -12,6 +12,7 @@ #include #include "atlas/library/config.h" +#include "atlas/field/MultiField.h" #include "atlas/field/detail/MultiFieldInterface.h" #include "atlas/runtime/Exception.h" @@ -21,6 +22,16 @@ namespace field { extern "C" { MultiFieldImpl* atlas__MultiField__create(eckit::Configuration* config) { ATLAS_ASSERT(config != nullptr); + + // Register in factory + // TODO: move __multiFieldCreatorIFS out of test_multifield_ifs.cc + //MultiFieldCreatorBuilder __MultiFieldCreatorIFS("MultiFieldCreatorIFS"); + + //MultiField* multifield = new MultiField(*config); + //return multifield->get(); + + // TODO + // repeat here the code for __multiFieldCreatorIFS out of test_multifield_ifs.cc long nproma = config->getLong("nproma"); long nlev = config->getLong("nlev"); long nblk = 0; @@ -123,8 +134,12 @@ void atlas__MultiField__delete(MultiFieldImpl* This) { delete This; } -FieldSet* atlas__MultiField__fieldset(MultiFieldImpl* This) { - return &This->fieldset(); +int atlas__MultiField__size(MultiFieldImpl* This) { + return This->size(); +} + +FieldSetImpl* atlas__MultiField__fieldset(MultiFieldImpl* This) { + return This->fieldset().get(); } } diff --git a/src/atlas/field/detail/MultiFieldInterface.h b/src/atlas/field/detail/MultiFieldInterface.h index f43990253..26ee8a268 100644 --- a/src/atlas/field/detail/MultiFieldInterface.h +++ b/src/atlas/field/detail/MultiFieldInterface.h @@ -31,7 +31,8 @@ namespace field { extern "C" { MultiFieldImpl* atlas__MultiField__create(eckit::Configuration* config); void atlas__MultiField__delete(MultiFieldImpl* This); -FieldSet* atlas__MultiField__fieldset(MultiFieldImpl* This); +int atlas__MultiField__size(MultiFieldImpl* This); +FieldSetImpl* atlas__MultiField__fieldset(MultiFieldImpl* This); } //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/atlas_f/CMakeLists.txt b/src/atlas_f/CMakeLists.txt index a065daad2..181b26aeb 100644 --- a/src/atlas_f/CMakeLists.txt +++ b/src/atlas_f/CMakeLists.txt @@ -218,7 +218,7 @@ ecbuild_add_library( TARGET atlas_f field/atlas_FieldSet_module.fypp field/atlas_State_module.F90 field/atlas_Field_module.fypp - field/atlas_MultiField_module.fypp + field/atlas_MultiField_module.F90 grid/atlas_Grid_module.F90 grid/atlas_GridDistribution_module.F90 grid/atlas_Vertical_module.F90 diff --git a/src/atlas_f/field/atlas_MultiField_module.F90 b/src/atlas_f/field/atlas_MultiField_module.F90 new file mode 100644 index 000000000..fd4cd09f1 --- /dev/null +++ b/src/atlas_f/field/atlas_MultiField_module.F90 @@ -0,0 +1,125 @@ +! (C) Copyright 2013 ECMWF. +! +! This software is licensed under the terms of the Apache Licence Version 2.0 +! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +! In applying this licence, ECMWF does not waive the privileges and immunities +! granted to it by virtue of its status as an intergovernmental organisation nor +! does it submit to any jurisdiction. + +#include "atlas/atlas_f.h" + +module atlas_multifield_module + +use fckit_owned_object_module, only : fckit_owned_object +use atlas_Config_module, only: atlas_Config +use atlas_fieldset_module, only: atlas_fieldset + +implicit none + +public :: atlas_MultiField + +private + +!------------------------------------------------------------------------------ +TYPE, extends(fckit_owned_object) :: atlas_MultiField + +! Purpose : +! ------- +! *MultiField* : Object containing field data and Metadata + +! Methods : +! ------- +! name : The name or tag this field was created with +! data : Return the field as a fortran array of specified shape +! Metadata : Return object that can contain a variety of Metadata + +! Author : +! ------ +! 20-Nov-2013 Willem Deconinck *ECMWF* +! 29-Aug-2023 Slavko Brdar *ECMWF* + +!------------------------------------------------------------------------------ +contains + procedure, public :: MultiField__fieldset + procedure, public :: MultiField__size + generic :: fieldset => MultiField__fieldset + generic :: size => MultiField__size + +#if FCKIT_FINAL_NOT_INHERITING + final :: atlas_MultiField__final_auto +#endif + +END TYPE + +interface atlas_MultiField + module procedure atlas_MultiField__cptr + module procedure atlas_MultiField__create +end interface + +private :: fckit_owned_object +private :: atlas_Config + +!======================================================== +contains +!======================================================== + +!------------------------------------------------------------------------------- + +function atlas_MultiField__cptr(cptr) result(field) + use, intrinsic :: iso_c_binding, only : c_ptr + type(atlas_MultiField) :: field + type(c_ptr), intent(in) :: cptr + call field%reset_c_ptr( cptr ) + call field%return() +end function + +!------------------------------------------------------------------------------- + +function atlas_MultiField__create(params) result(field) + use atlas_multifield_c_binding + type(atlas_MultiField) :: field + class(atlas_Config), intent(in) :: params + field = atlas_MultiField__cptr( atlas__MultiField__create(params%CPTR_PGIBUG_B) ) + call field%return() +end function + +!------------------------------------------------------------------------------- + +function MultiField__size(this) result(size) + use atlas_multifield_c_binding + class(atlas_MultiField), intent(in) :: this + integer :: size + size = atlas__MultiField__size(this%CPTR_PGIBUG_B) +end function + +!------------------------------------------------------------------------------- +function MultiField__fieldset(this) result(fset) + use, intrinsic :: iso_c_binding, only : c_ptr + use atlas_multifield_c_binding + class(atlas_MultiField), intent(in) :: this + type(c_ptr) :: fset_cptr + type(atlas_FieldSet) :: fset + fset_cptr = atlas__MultiField__fieldset(this%CPTR_PGIBUG_B) + fset = atlas_FieldSet( fset_cptr ) + call fset%return() +end function + +!------------------------------------------------------------------------------- + +#if FCKIT_FINAL_NOT_INHERITING +ATLAS_FINAL subroutine atlas_MultiField__final_auto(this) + type(atlas_MultiField), intent(inout) :: this +#if FCKIT_FINAL_DEBUGGING + write(0,*) "atlas_MultiField__final_auto" +#endif +#if FCKIT_FINAL_NOT_PROPAGATING + call this%final() +#endif + FCKIT_SUPPRESS_UNUSED( this ) +end subroutine +#endif + +!------------------------------------------------------------------------------- + +end module atlas_multifield_module + diff --git a/src/tests/field/fctest_multifield_ifs.F90 b/src/tests/field/fctest_multifield_ifs.F90 index 5c4b7a3ad..bf8bb276d 100644 --- a/src/tests/field/fctest_multifield_ifs.F90 +++ b/src/tests/field/fctest_multifield_ifs.F90 @@ -23,7 +23,7 @@ module fcta_MultiField_fixture ! ----------------------------------------------------------------------------- -TESTSUITE_WITH_FIXTURE(fctest_atlas_MultiField,fcta_MultiField_fixture) +TESTSUITE_WITH_FIXTURE(fctest_atlas_MultiField, fcta_MultiField_fixture) ! ----------------------------------------------------------------------------- @@ -46,6 +46,7 @@ module fcta_MultiField_fixture type(atlas_FieldSet) :: fieldset_1, fieldset_2 type(atlas_Field) :: field type(atlas_config) :: config + real(c_double), pointer :: view(:,:,:) integer, parameter :: nvar = 5; integer, parameter :: nproma = 16; @@ -72,10 +73,20 @@ module fcta_MultiField_fixture call config%set("fields", field_configs) multifield = atlas_MultiField(config) + FCTEST_CHECK_EQUAL(multifield%size(), 5) fieldset_1 = multifield%fieldset() - call fieldset_2%add(fieldset_1) + FCTEST_CHECK_EQUAL(fieldset_1%size(), 5) + + fieldset_2 = atlas_FieldSet() + call fieldset_2%add(multifield%fieldset()) field = fieldset_2%field("density") + call field%data(view) + view(1,1,1) = 2 + + field = fieldset_1%field("density") + call field%data(view) + FCTEST_CHECK_EQUAL(view(1,1,1), 2) END_TEST ! ----------------------------------------------------------------------------- diff --git a/src/tests/field/test_multifield_ifs.cc b/src/tests/field/test_multifield_ifs.cc index ce11afa35..3186eec53 100644 --- a/src/tests/field/test_multifield_ifs.cc +++ b/src/tests/field/test_multifield_ifs.cc @@ -252,6 +252,14 @@ CASE("multifield_create") { EXPECT_EQ(multiarray.size(), nblk * nvar * nlev * nproma); } + + // access FieldSet through MultiField + auto fieldset = multifield->fieldset(); + auto field_v = array::make_view(fieldset.field("temperature")); + EXPECT_EQ(fieldset.size(), 5); + EXPECT(fieldset.has("temperature")); + EXPECT(fieldset.has("wind_u")); + EXPECT_EQ(field_v(1,2,3), 4); } SECTION("test registry") {