diff --git a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
index 4a9c99a7b2f..01d10959ab7 100644
--- a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
@@ -300,7 +300,7 @@ AquiferBoundaryCondition::KernelWrapper AquiferBoundaryCondition::createKernelWr
pressureInfluenceFunction.createKernelWrapper() );
}
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, AquiferBoundaryCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, AquiferBoundaryCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/CMakeLists.txt b/src/coreComponents/fieldSpecification/CMakeLists.txt
index 8dc6827d664..a2cb7bec632 100644
--- a/src/coreComponents/fieldSpecification/CMakeLists.txt
+++ b/src/coreComponents/fieldSpecification/CMakeLists.txt
@@ -25,12 +25,16 @@ Contains:
set( fieldSpecification_headers
DirichletBoundaryCondition.hpp
EquilibriumInitialCondition.hpp
+ FieldSpecificationABC.hpp
FieldSpecificationBase.hpp
+ FieldSpecificationFactory.hpp
FieldSpecificationManager.hpp
SourceFluxBoundaryCondition.hpp
TractionBoundaryCondition.hpp
AquiferBoundaryCondition.hpp
PerfectlyMatchedLayer.hpp
+ PermeabilitySpecification.hpp
+ PermeabilitySpecificationFactory.hpp
)
#
@@ -39,12 +43,15 @@ set( fieldSpecification_headers
set( fieldSpecification_sources
DirichletBoundaryCondition.cpp
EquilibriumInitialCondition.cpp
+ FieldSpecificationABC.cpp
FieldSpecificationBase.cpp
FieldSpecificationManager.cpp
SourceFluxBoundaryCondition.cpp
TractionBoundaryCondition.cpp
AquiferBoundaryCondition.cpp
PerfectlyMatchedLayer.cpp
+ PermeabilitySpecification.cpp
+ PermeabilitySpecificationFactory.cpp
)
set( dependencyList ${parallelDeps} mesh )
diff --git a/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
index 19a62d921dd..99cfd1bbe04 100644
--- a/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
@@ -37,6 +37,6 @@ DirichletBoundaryCondition::~DirichletBoundaryCondition()
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, DirichletBoundaryCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, DirichletBoundaryCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp b/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp
index 6e0f1181e6e..2d1caf3a0d1 100644
--- a/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp
+++ b/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp
@@ -243,7 +243,7 @@ void EquilibriumInitialCondition::initializePreSubGroups()
}
}
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, EquilibriumInitialCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, EquilibriumInitialCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationABC.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationABC.cpp
new file mode 100644
index 00000000000..5d5a38d6704
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationABC.cpp
@@ -0,0 +1,36 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#include "FieldSpecificationABC.hpp"
+
+namespace geos
+{
+using namespace dataRepository;
+
+FieldSpecificationABC::FieldSpecificationABC( string const & name, Group * parent ):
+ Group( name, parent )
+{}
+
+FieldSpecificationABC::~FieldSpecificationABC()
+{}
+
+FieldSpecificationABC::CatalogInterface::CatalogType &
+FieldSpecificationABC::getCatalog()
+{
+ static FieldSpecificationABC::CatalogInterface::CatalogType catalog;
+ return catalog;
+}
+
+}
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationABC.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationABC.hpp
new file mode 100644
index 00000000000..9efab02e82f
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationABC.hpp
@@ -0,0 +1,107 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file FieldSpecificationABC.hpp
+ */
+
+#ifndef GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONABC_HPP
+#define GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONABC_HPP
+
+
+#include "common/DataTypes.hpp"
+#include "dataRepository/Group.hpp"
+#include "functions/FunctionBase.hpp"
+#include "functions/FunctionManager.hpp"
+
+namespace geos
+{
+class Function;
+
+
+/**
+ * @class FieldSpecificationABC
+ *
+ * Abstract Base Class grouping multiple types of field specifications.
+ */
+class FieldSpecificationABC : public dataRepository::Group
+{
+public:
+
+ /**
+ * @defgroup alias and functions to defined statically initialized catalog
+ * @{
+ */
+
+ /**
+ * alias to define the catalog type for this abstract type
+ */
+ using CatalogInterface = dataRepository::CatalogInterface< FieldSpecificationABC,
+ string const &,
+ dataRepository::Group * const >;
+
+ /**
+ * @brief static function to return static catalog.
+ * @return the static catalog to create derived types through the static factory methods.
+ */
+ static CatalogInterface::CatalogType & getCatalog();
+
+ /**
+ * @brief return the catalog name
+ * @return the catalog name
+ */
+ virtual const string getCatalogName() const = 0;
+
+ /**
+ * @}
+ */
+
+
+ /**
+ * @brief constructor
+ * @param name the name of the FieldSpecificationABC in the data repository
+ * @param parent the parent group of this group.
+ */
+ FieldSpecificationABC( string const & name, dataRepository::Group * parent );
+
+ /**
+ * destructor
+ */
+ virtual ~FieldSpecificationABC() override;
+
+
+ /// Deleted copy constructor
+ FieldSpecificationABC( FieldSpecificationABC const & ) = delete;
+
+ /// Defaulted move constructor
+ FieldSpecificationABC( FieldSpecificationABC && ) = default;
+
+ /// deleted copy assignment
+ FieldSpecificationABC & operator=( FieldSpecificationABC const & ) = delete;
+
+ /// deleted move assignement
+ FieldSpecificationABC & operator=( FieldSpecificationABC && ) = delete;
+
+ /**
+ * @brief View keys
+ */
+ struct viewKeyStruct
+ {};
+
+};
+
+}
+
+#endif //GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONABC_HPP
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp
index 94e78e7e06a..fbbbce616ee 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp
@@ -22,7 +22,7 @@ namespace geos
using namespace dataRepository;
FieldSpecificationBase::FieldSpecificationBase( string const & name, Group * parent ):
- Group( name, parent )
+ FieldSpecificationABC( name, parent )
{
setInputFlags( InputFlags::OPTIONAL_NONUNIQUE );
@@ -102,13 +102,6 @@ FieldSpecificationBase::FieldSpecificationBase( string const & name, Group * par
FieldSpecificationBase::~FieldSpecificationBase()
{}
-FieldSpecificationBase::CatalogInterface::CatalogType &
-FieldSpecificationBase::getCatalog()
-{
- static FieldSpecificationBase::CatalogInterface::CatalogType catalog;
- return catalog;
-}
-
void FieldSpecificationBase::setMeshObjectPath( Group const & meshBodies )
@@ -131,6 +124,6 @@ void FieldSpecificationBase::setMeshObjectPath( Group const & meshBodies )
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, FieldSpecificationBase, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, FieldSpecificationBase, string const &, Group * const )
}
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp
index 1905a4e5c36..6231bf2b1f2 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp
@@ -31,6 +31,7 @@
#include "mesh/MeshObjectPath.hpp"
#include "functions/FunctionManager.hpp"
#include "common/GEOS_RAJA_Interface.hpp"
+#include "FieldSpecificationABC.hpp"
namespace geos
{
@@ -41,21 +42,10 @@ class Function;
* @class FieldSpecificationBase
* A class to hold values for and administer a single boundary condition
*/
-class FieldSpecificationBase : public dataRepository::Group
+class FieldSpecificationBase : public FieldSpecificationABC
{
public:
- /**
- * @defgroup alias and functions to defined statically initialized catalog
- * @{
- */
-
- /**
- * alias to define the catalog type for this base type
- */
- using CatalogInterface = dataRepository::CatalogInterface< FieldSpecificationBase,
- string const &,
- dataRepository::Group * const >;
/**
* @enum SetErrorMode
* @brief Indicate the error handling mode.
@@ -67,12 +57,6 @@ class FieldSpecificationBase : public dataRepository::Group
warning
};
- /**
- * @brief static function to return static catalog.
- * @return the static catalog to create derived types through the static factory methods.
- */
- static CatalogInterface::CatalogType & getCatalog();
-
/**
* @brief Static Factory Catalog Functions
* @return the catalog name
@@ -88,10 +72,6 @@ class FieldSpecificationBase : public dataRepository::Group
return FieldSpecificationBase::catalogName();
}
- /**
- * @}
- */
-
/**
* @brief constructor
@@ -524,6 +504,24 @@ class FieldSpecificationBase : public dataRepository::Group
m_scale = scale;
}
+ /**
+ * Mutator
+ * @param[in] component The component index
+ */
+ void setComponent( int component )
+ {
+ m_component = component;
+ }
+
+ /**
+ * Mutator
+ * @param[in] functionName The name of the function
+ */
+ void setFunctionName( string const & functionName )
+ {
+ m_functionName = functionName;
+ }
+
/**
* Mutator
* @param[in] isInitialCondition Logical value to indicate if it is an initial condition
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationFactory.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.hpp
new file mode 100644
index 00000000000..32fc2d8aa34
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.hpp
@@ -0,0 +1,59 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file FieldSpecificationFactory.hpp
+ */
+
+#ifndef GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
+#define GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
+
+
+#include "common/DataTypes.hpp"
+#include "dataRepository/Group.hpp"
+#include "FieldSpecificationABC.hpp"
+
+namespace geos
+{
+
+/**
+ * @class FieldSpecificationFactory
+ *
+ * This class provides a way to create FieldSpecification objects using
+ * other type of specifications. One could think of those types of
+ * specification to blueprints or "high-level" specification
+ */
+class FieldSpecificationFactory
+{
+public:
+
+ /// @brief Generate FieldSpecifications based on the given "higher-level"
+ /// specification
+ /// @param specification The higher-level specification used as a blueprint
+ /// to create FieldSpecification
+ /// @param manager The parent to store the created FieldSpecifications
+ virtual void generate( FieldSpecificationABC const & specification,
+ dataRepository::Group & manager ) const = 0;
+
+ /// @return The key that represents the element this factory is about.
+ /// Purpose: link the factory to the specification it uses.
+ virtual string const getKey() const = 0;
+
+};
+
+}
+
+
+#endif //GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
index 6697c275715..2fb9d7e90b1 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
@@ -14,9 +14,13 @@
*/
#include "FieldSpecificationManager.hpp"
+#include "FieldSpecificationABC.hpp"
#include "mesh/DomainPartition.hpp"
#include "mesh/MeshBody.hpp"
#include "mesh/MeshObjectPath.hpp"
+#include "PermeabilitySpecification.hpp"
+#include "FieldSpecificationFactory.hpp"
+#include "PermeabilitySpecificationFactory.hpp"
namespace geos
{
@@ -34,6 +38,7 @@ FieldSpecificationManager::FieldSpecificationManager( string const & name, Group
GEOS_ERROR_IF( m_instance != nullptr, "Only one FieldSpecificationManager can exist at a time." );
m_instance = this;
+ registerFactory( std::make_unique< PermeabilitySpecificationFactory >() );
}
FieldSpecificationManager::~FieldSpecificationManager()
@@ -53,8 +58,8 @@ FieldSpecificationManager & FieldSpecificationManager::getInstance()
Group * FieldSpecificationManager::createChild( string const & childKey, string const & childName )
{
GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) );
- std::unique_ptr< FieldSpecificationBase > bc =
- FieldSpecificationBase::CatalogInterface::factory( childKey, getDataContext(), childName, this );
+ std::unique_ptr< FieldSpecificationABC > bc =
+ FieldSpecificationABC::CatalogInterface::factory( childKey, getDataContext(), childName, this );
return &this->registerGroup( childName, std::move( bc ) );
}
@@ -62,12 +67,29 @@ Group * FieldSpecificationManager::createChild( string const & childKey, string
void FieldSpecificationManager::expandObjectCatalogs()
{
// During schema generation, register one of each type derived from BoundaryConditionBase here
- for( auto & catalogIter: FieldSpecificationBase::getCatalog())
+ for( auto & catalogIter: FieldSpecificationABC::getCatalog())
{
createChild( catalogIter.first, catalogIter.first );
}
}
+void FieldSpecificationManager::registerFactory( std::unique_ptr< FieldSpecificationFactory > factory )
+{
+ m_factories.emplace( factory->getKey(), std::move( factory ) );
+}
+
+void FieldSpecificationManager::postInputInitialization()
+{
+ forSubGroups< FieldSpecificationABC >( [&]( FieldSpecificationABC const & spec )
+ {
+ auto it = m_factories.find( spec.getCatalogName() );
+ if( it != m_factories.end() )
+ {
+ it->second->generate( spec, *this );
+ }
+ } );
+}
+
void FieldSpecificationManager::validateBoundaryConditions( MeshLevel & mesh ) const
{
DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" );
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
index b1d929e6561..1ec2e387515 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
@@ -21,6 +21,7 @@
#define GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONMANAGER_HPP_
#include "FieldSpecificationBase.hpp"
+#include "FieldSpecificationFactory.hpp"
#include "common/format/StringUtilities.hpp"
#include "common/DataTypes.hpp"
@@ -238,11 +239,28 @@ class FieldSpecificationManager : public dataRepository::Group
m_isSurfaceGenerationCase = isSurfaceGenerationCase;
}
+ /**
+ * @brief Register a factory in the manager to create FieldSpecification
+ * via "high-level" field specifications data
+ * @param factory The factory to add to the manager
+ */
+ void registerFactory( std::unique_ptr< FieldSpecificationFactory > factory );
+
+
+protected:
+
+ virtual void postInputInitialization() override;
+
+
private:
+
static FieldSpecificationManager * m_instance;
+
/// Indicate if the SurfaceGenerator element is present
bool m_isSurfaceGenerationCase = false;
+ std::unordered_map< string, std::unique_ptr< FieldSpecificationFactory > > m_factories;
+
};
template< typename POLICY, typename LAMBDA >
diff --git a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
index 7e71480536c..1a946c97c23 100644
--- a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
+++ b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
@@ -121,6 +121,6 @@ void PerfectlyMatchedLayer::postInputInitialization()
}
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, PerfectlyMatchedLayer, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, PerfectlyMatchedLayer, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/PermeabilitySpecification.cpp b/src/coreComponents/fieldSpecification/PermeabilitySpecification.cpp
new file mode 100644
index 00000000000..22a5c6ec77f
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecification.cpp
@@ -0,0 +1,68 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#include "PermeabilitySpecification.hpp"
+
+namespace geos
+{
+using namespace dataRepository;
+
+PermeabilitySpecification::PermeabilitySpecification( string const & name, Group * parent ):
+ FieldSpecificationABC( name, parent )
+{
+ setInputFlags( InputFlags::OPTIONAL_NONUNIQUE );
+
+ registerWrapper( viewKeyStruct::setNamesString(), &m_setNames ).
+ setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
+ setInputFlag( InputFlags::REQUIRED ).
+ setSizedFromParent( 0 ).
+ setDescription( "Names of sets that the boundary condition is applied to.\n"
+ "A set can contain heterogeneous elements in the mesh (volumes, nodes, faces, edges).\n"
+ "A set can be be defined by a 'Geometry' component, or correspond to imported sets in case of an external mesh" );
+
+ registerWrapper( viewKeyStruct::regionNamesString(), &m_regionNames ).
+ setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
+ setInputFlag( InputFlags::REQUIRED ).
+ setDescription( "Names of the regions that boundary condition is applied to." );
+
+ registerWrapper( viewKeyStruct::fieldNameString(), &m_fieldName ).
+ setRTTypeName( rtTypes::CustomTypes::groupNameRef ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Name of field that boundary condition is applied to.\n"
+ "A field can represent a physical variable. (pressure, temperature, global composition fraction of the fluid, ...)" );
+
+ registerWrapper( viewKeyStruct::functionNameString(), &m_functionName ).
+ setRTTypeName( rtTypes::CustomTypes::groupNameRef ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Name of function that specifies variation of the boundary condition." );
+
+ registerWrapper( viewKeyStruct::scalesString(), &m_scales ).
+ setApplyDefaultValue( { 0.0, 0.0, 0.0 } ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Apply a scaling factor for the value of the boundary condition." );
+}
+
+
+PermeabilitySpecification::~PermeabilitySpecification()
+{}
+
+
+void PermeabilitySpecification::postInputInitialization()
+{}
+
+
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, PermeabilitySpecification, string const &, Group * const )
+
+}
diff --git a/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp b/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp
new file mode 100644
index 00000000000..86cd7bec59b
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp
@@ -0,0 +1,172 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file PermeabilitySpecification.hpp
+ */
+
+#ifndef GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATION_HPP
+#define GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATION_HPP
+
+
+#include "common/DataTypes.hpp"
+#include "mesh/ObjectManagerBase.hpp"
+#include "mesh/MeshObjectPath.hpp"
+#include "FieldSpecificationABC.hpp"
+
+namespace geos
+{
+
+/**
+ * @class PermeabilitySpecification
+ *
+ * Data class representing a permeability field specification
+ */
+class PermeabilitySpecification : public FieldSpecificationABC
+{
+public:
+
+ /**
+ * @brief Static Factory Catalog Functions
+ * @return the catalog name
+ */
+ static string catalogName() { return "PermeabilitySpecification"; }
+
+ /**
+ * @brief return the catalog name
+ * @return the catalog name
+ */
+ virtual const string getCatalogName() const
+ {
+ return PermeabilitySpecification::catalogName();
+ }
+
+
+ /**
+ * @brief constructor
+ * @param name the name of the PermeabilitySpecification in the data repository
+ * @param parent the parent group of this group.
+ */
+ PermeabilitySpecification( string const & name, dataRepository::Group * parent );
+
+ /**
+ * destructor
+ */
+ virtual ~PermeabilitySpecification() override;
+
+
+ /// Deleted copy constructor
+ PermeabilitySpecification( PermeabilitySpecification const & ) = delete;
+
+ /// Defaulted move constructor
+ PermeabilitySpecification( PermeabilitySpecification && ) = default;
+
+ /// deleted copy assignment
+ PermeabilitySpecification & operator=( PermeabilitySpecification const & ) = delete;
+
+ /// deleted move assignement
+ PermeabilitySpecification & operator=( PermeabilitySpecification && ) = delete;
+
+ /**
+ * @brief View keys
+ */
+ struct viewKeyStruct
+ {
+ /// @return The key for setName
+ constexpr static char const * setNamesString() { return "setNames"; }
+ /// @return The key for regionNames
+ constexpr static char const * regionNamesString() { return "regionNames"; }
+ /// @return The key for fieldName
+ constexpr static char const * fieldNameString() { return "fieldName"; }
+ /// @return The key for functionName
+ constexpr static char const * functionNameString() { return "functionName"; }
+ /// @return The key for scales
+ constexpr static char const * scalesString() { return "scales"; }
+ };
+
+ /**
+ * Accessor
+ * @return const reference to m_function
+ */
+ string const & getFunctionName() const
+ {
+ return m_functionName;
+ }
+
+ /**
+ * Accessor
+ * @return const reference to m_regionNames
+ */
+ string_array const & getRegionNames() const
+ {
+ return m_regionNames;
+ }
+
+ /**
+ * Accessor
+ * @return const reference to m_fieldName
+ */
+ virtual const string & getFieldName() const
+ {
+ return m_fieldName;
+ }
+
+ /**
+ * Accessor
+ * @return const reference to m_setNames
+ */
+ string_array const & getSetNames() const
+ {
+ return m_setNames;
+ }
+
+ /**
+ * Accessor
+ * @return const m_scales
+ */
+ R1Tensor getScales() const
+ {
+ return m_scales;
+ }
+
+
+protected:
+
+ virtual void postInputInitialization() override;
+
+private:
+
+
+ /// the names of the sets that the boundary condition is applied to
+ string_array m_setNames;
+
+ /// the names of the regions that the boundary condition is applied to
+ string_array m_regionNames;
+
+ /// the name of the field the boundary condition is applied to or a key string to use for
+ /// determining whether or not to apply the boundary condition.
+ string m_fieldName;
+
+ /// The name of the function used to generate values for application.
+ string m_functionName;
+
+ /// The scale factors to use on the value of the boundary condition.
+ R1Tensor m_scales;
+
+};
+
+}
+
+#endif //GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATION_HPP
diff --git a/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.cpp b/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.cpp
new file mode 100644
index 00000000000..d1791a03046
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.cpp
@@ -0,0 +1,73 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file PermeabilitySpecificationFactory.cpp
+ */
+
+#include "PermeabilitySpecificationFactory.hpp"
+#include "common/DataTypes.hpp"
+#include "dataRepository/Group.hpp"
+#include "PermeabilitySpecification.hpp"
+#include "FieldSpecificationABC.hpp"
+#include "FieldSpecificationBase.hpp"
+
+namespace geos
+{
+
+/**
+ * @class PermeabilitySpecificationFactory
+ */
+
+void PermeabilitySpecificationFactory::generate( FieldSpecificationABC const & specification,
+ dataRepository::Group & manager ) const
+{
+ auto ps = dynamic_cast< PermeabilitySpecification const * >( &specification );
+
+ stdArray< string, 3 > suffixes = {{ "_x", "_y", "_z" }};
+
+ R1Tensor scales = ps->getScales();
+
+ for( string const & regionName : ps->getRegionNames() )
+ {
+ string const objectPath = "ElementRegions/" + regionName;
+
+ for( integer comp = 0; comp < 3; ++comp )
+ {
+ string const childName = ps->getName() + "_" + regionName + suffixes[ comp ];
+
+ FieldSpecificationBase & fs = manager.registerGroup< FieldSpecificationBase >( childName );
+ fs.setFieldName( ps->getFieldName() );
+ fs.setObjectPath( objectPath );
+ fs.setScale( scales[ comp ] );
+ fs.initialCondition( true );
+ fs.setComponent( comp );
+
+ for( auto const & setName : ps->getSetNames() )
+ {
+ fs.addSetName( setName );
+ }
+
+ if( !ps->getFunctionName().empty() )
+ {
+ fs.setFunctionName( ps->getFunctionName() );
+ }
+
+ }
+ }
+
+}
+
+}
diff --git a/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.hpp b/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.hpp
new file mode 100644
index 00000000000..d8f85b16fb3
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecificationFactory.hpp
@@ -0,0 +1,57 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file PermeabilitySpecificationFactory.hpp
+ */
+
+#ifndef GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATIONFACTORY_HPP
+#define GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATIONFACTORY_HPP
+
+
+#include "common/DataTypes.hpp"
+#include "dataRepository/Group.hpp"
+#include "PermeabilitySpecification.hpp"
+#include "FieldSpecificationABC.hpp"
+#include "FieldSpecificationBase.hpp"
+#include "FieldSpecificationFactory.hpp"
+
+namespace geos
+{
+
+/**
+ * @class PermeabilitySpecificationFactory
+ *
+ * @copydoc geos::FieldSpecificationFactory
+ * Field specification factory implementation for the PermeabilitySpecification
+ */
+class PermeabilitySpecificationFactory : public FieldSpecificationFactory
+{
+public:
+
+ /// @copydoc geos::FieldSpecificationFactory::generate()
+ void generate( FieldSpecificationABC const & specification,
+ dataRepository::Group & manager ) const;
+
+ /// @copydoc geos::FieldSpecificationFactory::getKey()
+ string const getKey() const
+ {
+ return PermeabilitySpecification::catalogName();
+ }
+};
+
+}
+
+#endif //GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATIONFACTORY_HPP
diff --git a/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
index 8a05108fe9d..0aad1e3102d 100644
--- a/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
@@ -43,6 +43,6 @@ SourceFluxBoundaryCondition::SourceFluxBoundaryCondition( string const & name, G
FieldSpecificationBase::viewKeyStruct::functionNameString() ) );
}
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, SourceFluxBoundaryCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, SourceFluxBoundaryCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp
index 49392b016f0..a66dd9f4f8f 100644
--- a/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp
@@ -437,7 +437,7 @@ void TractionBoundaryCondition::reinitScaleSet( FaceManager const & faceManager,
} );
}
-REGISTER_CATALOG_ENTRY( FieldSpecificationBase, TractionBoundaryCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, TractionBoundaryCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/docs/FieldSpecification.rst b/src/coreComponents/fieldSpecification/docs/FieldSpecification.rst
index 7752ed84863..b52ebee4449 100644
--- a/src/coreComponents/fieldSpecification/docs/FieldSpecification.rst
+++ b/src/coreComponents/fieldSpecification/docs/FieldSpecification.rst
@@ -9,4 +9,6 @@ Initial and Boundary Conditions
EquilibriumInitialCondition
AquiferBoundaryCondition
+
+ PermeabilitySpecification
diff --git a/src/coreComponents/fieldSpecification/docs/PermeabilitySpecification.rst b/src/coreComponents/fieldSpecification/docs/PermeabilitySpecification.rst
new file mode 100644
index 00000000000..55f324f5c02
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/docs/PermeabilitySpecification.rst
@@ -0,0 +1,49 @@
+.. _PermeabilitySpecification:
+
+####################################################
+Permeability specification
+####################################################
+
+Overview
+======================
+
+**PermeabilitySpecification** is an optional, higher-level XML tag that you can place in the **FieldSpecifications** block.
+It describes a 3-axis permeability on one or more element regions.
+After the input deck is read, GEOS expands each **PermeabilitySpecification** into several **FieldSpecification** objects (one per region and per axis) that the rest of the code already understands.
+
+This is convenient when you want the same **setNames**, **fieldName**, and other attributes for all three permeability components, instead of repeating three nearly identical **FieldSpecification**.
+
+Examples
+===============
+
+The following illustrates a **PermeabilitySpecification** for a single region.
+
+.. code-block:: xml
+
+
+ ...
+
+ ...
+
+
+The following illustrates a **PermeabilitySpecification** for multiple regions.
+
+.. code-block:: xml
+
+
+ ...
+
+ ...
+