-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #229 from ecmwf/feature/MultiField
Add MultiField to pack field allocations
- Loading branch information
Showing
18 changed files
with
1,935 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* (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/field/MultiField.h" | ||
|
||
#include <iomanip> | ||
#include <map> | ||
#include <memory> | ||
#include <sstream> | ||
#include <string> | ||
#include <mutex> | ||
|
||
#include "atlas/field/MultiFieldCreator.h" | ||
#include "atlas/field/detail/MultiFieldImpl.h" | ||
#include "atlas/runtime/Exception.h" | ||
|
||
namespace atlas { | ||
namespace field { | ||
|
||
//----------------------------------------------------------------------------- | ||
|
||
MultiField::MultiField(const eckit::Configuration& config) { | ||
std::string type; | ||
if (!config.get("type", type)) { | ||
ATLAS_THROW_EXCEPTION("Could not find \"type\" in configuration"); | ||
} | ||
std::unique_ptr<MultiFieldCreator> creator(MultiFieldCreatorFactory::build(type, config)); | ||
reset(creator->create(config)); | ||
} | ||
|
||
MultiField::MultiField(const array::DataType datatype, const std::vector<int>& shape, | ||
const std::vector<std::string>& var_names) { | ||
std::unique_ptr<MultiFieldCreator> creator(MultiFieldCreatorFactory::build("MultiFieldCreatorArray")); | ||
reset(creator->create(datatype, shape, var_names)); | ||
} | ||
|
||
const Field& MultiField::field(const std::string& name) const { return get()->field(name); } | ||
Field& MultiField::field(const std::string& name) { return get()->field(name); } | ||
bool MultiField::has(const std::string& name) const { return get()->has(name); } | ||
std::vector<std::string> MultiField::field_names() const { return get()->field_names(); } | ||
|
||
const Field& MultiField::field(const idx_t idx) const { return get()->field(idx); } | ||
Field& MultiField::field(const idx_t idx) { return get()->field(idx); } | ||
idx_t MultiField::size() const { return get()->size(); } | ||
|
||
const Field& MultiField::operator[](const idx_t idx) const { return get()->field(idx); } | ||
Field& MultiField::operator[](const idx_t idx) { return get()->field(idx); } | ||
|
||
const Field& MultiField::operator[](const std::string& name) const { return get()->field(name); } | ||
Field& MultiField::operator[](const std::string& name) { return get()->field(name); } | ||
|
||
const util::Metadata& MultiField::metadata() const { return get()->metadata(); } | ||
util::Metadata& MultiField::metadata() { return get()->metadata(); } | ||
|
||
MultiField::operator const array::Array&() const { return get()->array(); } | ||
MultiField::operator array::Array&() { return get()->array(); } | ||
|
||
MultiField::operator const FieldSet&() const { return get()->fieldset_; } | ||
MultiField::operator FieldSet&() { return get()->fieldset_; } | ||
|
||
const array::Array& MultiField::array() const { return get()->array(); } | ||
array::Array& MultiField::array() { return get()->array(); } | ||
|
||
//----------------------------------------------------------------------------- | ||
|
||
} // namespace field | ||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* | ||
* (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. | ||
*/ | ||
|
||
/// @author Willem Deconinck | ||
/// @date June 2015 | ||
|
||
#pragma once | ||
|
||
#include <map> | ||
#include <vector> | ||
|
||
#include "atlas/array/Array.h" | ||
#include "atlas/field/Field.h" | ||
#include "atlas/field/FieldSet.h" | ||
#include "atlas/util/Config.h" | ||
#include "atlas/util/Factory.h" | ||
#include "atlas/util/Metadata.h" | ||
#include "atlas/util/Object.h" | ||
#include "atlas/util/ObjectHandle.h" | ||
|
||
namespace eckit { | ||
class Parametrisation; | ||
} | ||
|
||
namespace atlas { | ||
namespace field { | ||
class MultiFieldImpl; | ||
} | ||
} | ||
|
||
namespace atlas { | ||
namespace field { | ||
|
||
/** | ||
* \brief MultiField class that owns a collection of fields that are co-allocated | ||
* | ||
* Fields can only be described by parametrisation during the construction. | ||
* Once setup, no additional fields can be added. | ||
* | ||
* Fields have to all be of same memory layout and data type | ||
*/ | ||
|
||
class MultiField : public util::ObjectHandle<MultiFieldImpl> { | ||
public: // methods | ||
//-- Constructors | ||
using Handle::Handle; | ||
|
||
MultiField(const eckit::Configuration&); | ||
MultiField(const array::DataType datatype, const std::vector<int>& shape, | ||
const std::vector<std::string>& var_names); | ||
|
||
//-- Accessors | ||
|
||
const Field& field(const std::string& name) const; | ||
Field& field(const std::string& name); | ||
bool has(const std::string& name) const; | ||
std::vector<std::string> field_names() const; | ||
|
||
const Field& field(const idx_t idx) const; | ||
Field& field(const idx_t idx); | ||
idx_t size() const; | ||
|
||
const Field& operator[](const idx_t idx) const; | ||
Field& operator[](const idx_t idx); | ||
|
||
const Field& operator[](const std::string& name) const; | ||
Field& operator[](const std::string& name); | ||
|
||
const util::Metadata& metadata() const; | ||
util::Metadata& metadata(); | ||
|
||
// -- Modifiers | ||
|
||
/// @brief Implicit conversion to Array | ||
operator const array::Array&() const; | ||
operator array::Array&(); | ||
|
||
operator const FieldSet&() const; | ||
operator FieldSet&(); | ||
|
||
/// @brief Access contained Array | ||
const array::Array& array() const; | ||
array::Array& array(); | ||
|
||
private: | ||
template<typename datatype> | ||
void create(const std::vector<int> shape, const std::vector<std::string> var_names); | ||
}; | ||
|
||
/** | ||
* \brief MultiFieldArrayRegistry | ||
*/ | ||
|
||
class MultiFieldArrayRegistry : public field::FieldObserver { | ||
private: | ||
MultiFieldArrayRegistry() {} | ||
|
||
public: | ||
static MultiFieldArrayRegistry& instance() { | ||
static MultiFieldArrayRegistry inst; | ||
return inst; | ||
} | ||
void onFieldDestruction(FieldImpl& field) override { | ||
std::lock_guard<std::mutex> guard(lock_); | ||
map_.erase(&field); | ||
} | ||
|
||
~MultiFieldArrayRegistry() override = default; | ||
|
||
void add(Field& field, std::shared_ptr<array::Array> array) { | ||
std::lock_guard<std::mutex> guard(lock_); | ||
map_.emplace(field.get(), array); | ||
field->attachObserver(*this); | ||
} | ||
|
||
public: | ||
std::mutex lock_; | ||
std::map<FieldImpl*,std::shared_ptr<array::Array>> map_; | ||
|
||
}; | ||
|
||
// ------------------------------------------------------------------------------------ | ||
|
||
} // namespace field | ||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* (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. | ||
*/ | ||
|
||
// file deepcode ignore CppMemoryLeak: static pointers for global registry are OK and will be cleaned up at end | ||
|
||
#include "atlas/field/MultiFieldCreator.h" | ||
|
||
#include <map> | ||
#include <sstream> | ||
|
||
#include "eckit/thread/AutoLock.h" | ||
#include "eckit/thread/Mutex.h" | ||
|
||
#include "atlas/field/MultiFieldCreatorIFS.h" | ||
#include "atlas/field/MultiFieldCreatorArray.h" | ||
#include "atlas/grid/Grid.h" | ||
#include "atlas/runtime/Exception.h" | ||
#include "atlas/runtime/Log.h" | ||
|
||
|
||
namespace atlas { | ||
namespace field { | ||
|
||
|
||
namespace { | ||
|
||
void force_link() { | ||
static struct Link { | ||
Link() { | ||
MultiFieldCreatorBuilder<MultiFieldCreatorIFS>(); | ||
MultiFieldCreatorBuilder<MultiFieldCreatorArray>(); | ||
} | ||
} link; | ||
} | ||
|
||
} // namespace | ||
|
||
// ------------------------------------------------------------------ | ||
|
||
MultiFieldCreator::MultiFieldCreator() = default; | ||
|
||
MultiFieldCreator::~MultiFieldCreator() = default; | ||
|
||
MultiFieldCreator* MultiFieldCreatorFactory::build(const std::string& builder, const eckit::Configuration& config) { | ||
force_link(); | ||
auto factory = get(builder); | ||
return factory->make(config); | ||
} | ||
|
||
} // namespace field | ||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* (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. | ||
*/ | ||
|
||
#ifndef atlas_field_MultiFieldCreator_h | ||
#define atlas_field_MultiFieldCreator_h | ||
|
||
#include <string> | ||
|
||
#include "atlas/util/Object.h" | ||
|
||
#include "atlas/field/MultiField.h" | ||
|
||
namespace eckit { | ||
class Configuration; | ||
} | ||
|
||
//------------------------------------------------------------------------------------------------------ | ||
|
||
namespace atlas { | ||
namespace field { | ||
|
||
//------------------------------------------------------------------------------------------------------ | ||
|
||
/*! | ||
* \brief Base class for creating new multifields based on Configuration | ||
* | ||
* \details | ||
* Example to create field[100][3] of default type double: | ||
* \code{.cpp} | ||
* FieldImpl* field = Field::create( | ||
* Config | ||
* ("creator","ArraySpec") // ArraySpec MultiFieldCreator | ||
* ("shape",array::make_shape(100,3)) // Rank 2 field with indexing [100][3] | ||
* ); | ||
* \endcode | ||
*/ | ||
class MultiFieldCreator : public util::Object { | ||
public: | ||
MultiFieldCreator(); | ||
MultiFieldCreator(const eckit::Configuration& config); | ||
|
||
virtual ~MultiFieldCreator(); | ||
|
||
virtual MultiFieldImpl* create(const eckit::Configuration& config = util::Config()) const = 0; | ||
virtual MultiFieldImpl* create(const array::DataType datatype, const std::vector<int>& shape, | ||
const std::vector<std::string>& var_names) const = 0; | ||
}; | ||
|
||
//------------------------------------------------------------------------------------------------------ | ||
|
||
class MultiFieldCreatorFactory : public util::Factory<MultiFieldCreatorFactory> { | ||
public: | ||
static std::string className() { return "MultiFieldCreatorFactory"; } | ||
|
||
/*! | ||
* \brief build MultiFieldCreator with options specified in parametrisation | ||
* \return mesh generator | ||
*/ | ||
static MultiFieldCreator* build(const std::string&, const eckit::Configuration& = util::Config()); | ||
|
||
using Factory::Factory; | ||
|
||
private: | ||
virtual MultiFieldCreator* make() = 0; | ||
virtual MultiFieldCreator* make(const eckit::Configuration&) = 0; | ||
}; | ||
|
||
template <class T> | ||
class MultiFieldCreatorBuilder : public MultiFieldCreatorFactory { | ||
virtual MultiFieldCreator* make() { return new T(); } | ||
virtual MultiFieldCreator* make(const eckit::Configuration& config) { return new T(config); } | ||
|
||
public: | ||
using MultiFieldCreatorFactory::MultiFieldCreatorFactory; | ||
}; | ||
|
||
//------------------------------------------------------------------------------------------------------ | ||
|
||
} // namespace field | ||
} // namespace atlas | ||
|
||
#endif |
Oops, something went wrong.