diff --git a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
index 6627fc299e8..518a8916be5 100644
--- a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp
@@ -304,7 +304,7 @@ AquiferBoundaryCondition::KernelWrapper AquiferBoundaryCondition::createKernelWr
pressureInfluenceFunction.createKernelWrapper() );
}
-REGISTER_CATALOG_ENTRY( FieldSpecification, 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 1ab2ae911b0..07c83728d5e 100644
--- a/src/coreComponents/fieldSpecification/CMakeLists.txt
+++ b/src/coreComponents/fieldSpecification/CMakeLists.txt
@@ -26,12 +26,15 @@ set( fieldSpecification_headers
DirichletBoundaryCondition.hpp
EquilibriumInitialCondition.hpp
FieldSpecification.hpp
+ FieldSpecificationABC.hpp
+ FieldSpecificationFactory.hpp
FieldSpecificationManager.hpp
FieldSpecificationImpl.hpp
SourceFluxBoundaryCondition.hpp
TractionBoundaryCondition.hpp
AquiferBoundaryCondition.hpp
PerfectlyMatchedLayer.hpp
+ PermeabilitySpecification.hpp
)
#
@@ -41,11 +44,14 @@ set( fieldSpecification_sources
DirichletBoundaryCondition.cpp
EquilibriumInitialCondition.cpp
FieldSpecification.cpp
+ FieldSpecificationABC.cpp
+ FieldSpecificationFactory.cpp
FieldSpecificationManager.cpp
SourceFluxBoundaryCondition.cpp
TractionBoundaryCondition.cpp
AquiferBoundaryCondition.cpp
PerfectlyMatchedLayer.cpp
+ PermeabilitySpecification.cpp
)
set( dependencyList ${parallelDeps} mesh )
diff --git a/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
index 31ce54725c0..0b4733e0fcf 100644
--- a/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/DirichletBoundaryCondition.cpp
@@ -37,6 +37,6 @@ DirichletBoundaryCondition::~DirichletBoundaryCondition()
-REGISTER_CATALOG_ENTRY( FieldSpecification, 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 d92fe6a1893..27b40a7d460 100644
--- a/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp
+++ b/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp
@@ -245,7 +245,7 @@ void EquilibriumInitialCondition::initializePreSubGroups()
}
}
-REGISTER_CATALOG_ENTRY( FieldSpecification, EquilibriumInitialCondition, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, EquilibriumInitialCondition, string const &, Group * const )
} /* namespace geos */
diff --git a/src/coreComponents/fieldSpecification/FieldSpecification.cpp b/src/coreComponents/fieldSpecification/FieldSpecification.cpp
index 7923b0fcfb4..fa7d1a6d333 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecification.cpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecification.cpp
@@ -20,7 +20,7 @@ namespace geos
using namespace dataRepository;
FieldSpecification::FieldSpecification( string const & name, Group * parent ):
- Group( name, parent )
+ FieldSpecificationABC( name, parent )
{
setInputFlags( InputFlags::OPTIONAL_NONUNIQUE );
@@ -184,6 +184,6 @@ void FieldSpecification::setMeshObjectPath( Group const & meshBodies )
-REGISTER_CATALOG_ENTRY( FieldSpecification, FieldSpecification, string const &, Group * const )
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, FieldSpecification, string const &, Group * const )
}
diff --git a/src/coreComponents/fieldSpecification/FieldSpecification.hpp b/src/coreComponents/fieldSpecification/FieldSpecification.hpp
index 019f50d6145..8df1b265c7f 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecification.hpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecification.hpp
@@ -24,6 +24,7 @@
#include "common/DataTypes.hpp"
#include "common/format/EnumStrings.hpp"
#include "dataRepository/Group.hpp"
+#include "fieldSpecification/FieldSpecificationABC.hpp"
#include "mesh/MeshObjectPath.hpp"
namespace geos
@@ -35,7 +36,7 @@ class Function;
* @class FieldSpecification
* A class to hold values for and administer a single boundary condition
*/
-class FieldSpecification : public dataRepository::Group
+class FieldSpecification : public FieldSpecificationABC
{
public:
@@ -247,6 +248,13 @@ class FieldSpecification : public dataRepository::Group
void setFieldName( string const & fieldName )
{ m_fieldName = fieldName; }
+ /**
+ * Mutator
+ * @param[in] component The component axis or a special value.
+ */
+ void setComponent( int component )
+ { m_component = component; }
+
/**
* Mutator
* @param[in] objectPath The path for the object
@@ -302,6 +310,27 @@ class FieldSpecification : public dataRepository::Group
*/
void setMeshObjectPath( Group const & meshBodies );
+ /**
+ * Mutator
+ * @param[in] beginTime Time after which the bc is allowed to be applied
+ */
+ void setStartTime( real64 beginTime )
+ { m_beginTime = beginTime; }
+
+ /**
+ * Mutator
+ * @param[in] endTime Time after which the bc will no longer be applied.
+ */
+ void setEndTime( real64 endTime )
+ { m_endTime = endTime; }
+
+ /**
+ * Mutator
+ * @param[in] errorSetMode Time after which the bc will no longer be applied.
+ */
+ void setErrorSetMode( SetErrorMode const & errorSetMode )
+ { m_emptySetErrorMode = errorSetMode; }
+
/**
* @brief Get the Mesh Object Paths object
*
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..b6262004884
--- /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 define 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/FieldSpecificationFactory.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.cpp
new file mode 100644
index 00000000000..c8440e7df5d
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.cpp
@@ -0,0 +1,47 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * 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.cpp
+ */
+
+#include "FieldSpecificationFactory.hpp"
+#include "PermeabilitySpecification.hpp"
+
+namespace geos
+{
+
+namespace
+{
+
+template< typename ... SPEC_TYPES, typename LAMBDA >
+void forExpandableSpecifications( dataRepository::Group & manager,
+ types::TypeList< SPEC_TYPES... >,
+ LAMBDA && lambda )
+{
+ manager.template forSubGroups< SPEC_TYPES... >( std::forward< LAMBDA >( lambda ) );
+}
+
+}
+
+void expandFieldSpecifications( dataRepository::Group & manager )
+{
+ forExpandableSpecifications( manager, ExpandableSpecTypes{}, [&]( auto const & spec )
+ {
+ generateFieldSpecifications( spec, manager );
+ } );
+}
+
+} // namespace geos
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationFactory.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.hpp
new file mode 100644
index 00000000000..c11e50357f0
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationFactory.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 FieldSpecificationFactory.hpp
+ */
+
+#ifndef GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
+#define GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
+
+
+#include "common/TypeDispatch.hpp"
+#include "dataRepository/Group.hpp"
+
+namespace geos
+{
+
+class PermeabilitySpecification;
+
+/**
+ * @brief List of high-level field specifications to expand into FieldSpecification objects.
+ */
+using ExpandableSpecTypes = types::TypeList< PermeabilitySpecification >;
+
+/**
+ * @brief Generate FieldSpecifications based on the given "higher-level" specification
+ * @tparam SPEC_TYPE The type of the high-level specification
+ * @param specification The high-level specification used as a blueprint
+ * to create FieldSpecification
+ * @param manager The parent to store the created FieldSpecifications
+ */
+template< typename SPEC_TYPE >
+void generateFieldSpecifications( SPEC_TYPE const & specification, dataRepository::Group & manager ) = delete;
+
+/**
+ * @brief Expand high-level field specifications
+ * @param manager The manager group
+ * Expand all field specificiation listed in ExpandableSpecTypes
+ */
+void expandFieldSpecifications( dataRepository::Group & manager );
+
+} // namespace geos
+
+
+#endif //GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONFACTORY_HPP
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationImpl.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationImpl.hpp
index 1385a606f82..7f25aaa5916 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationImpl.hpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationImpl.hpp
@@ -30,6 +30,7 @@
#include "mesh/MeshObjectPath.hpp"
#include "functions/FunctionManager.hpp"
#include "common/GEOS_RAJA_Interface.hpp"
+#include "FieldSpecificationABC.hpp"
namespace geos
{
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
index ea42c65bda0..af30af68166 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp
@@ -14,6 +14,8 @@
*/
#include "FieldSpecificationManager.hpp"
+#include "FieldSpecificationABC.hpp"
+#include "FieldSpecificationFactory.hpp"
#include "mesh/DomainPartition.hpp"
#include "mesh/MeshBody.hpp"
#include "mesh/MeshObjectPath.hpp"
@@ -33,7 +35,6 @@ FieldSpecificationManager::FieldSpecificationManager( string const & name, Group
GEOS_ERROR_IF( m_instance != nullptr, "Only one FieldSpecificationManager can exist at a time." );
m_instance = this;
-
}
FieldSpecificationManager::~FieldSpecificationManager()
@@ -53,8 +54,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< FieldSpecification > bc =
- FieldSpecification::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 +63,17 @@ 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: FieldSpecification::getCatalog())
+ for( auto & catalogIter: FieldSpecificationABC::getCatalog())
{
createChild( catalogIter.first, catalogIter.first );
}
}
+void FieldSpecificationManager::postInputInitialization()
+{
+ expandFieldSpecifications( *this );
+}
+
void FieldSpecificationManager::validateBoundaryConditions( MeshLevel & mesh )
{
DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" );
diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
index 6526f48178b..d5f931d0e56 100644
--- a/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
+++ b/src/coreComponents/fieldSpecification/FieldSpecificationManager.hpp
@@ -238,8 +238,16 @@ class FieldSpecificationManager : public dataRepository::Group
m_isSurfaceGenerationCase = isSurfaceGenerationCase;
}
+
+protected:
+
+ virtual void postInputInitialization() override;
+
+
private:
+
static FieldSpecificationManager * m_instance;
+
/// Indicate if the SurfaceGenerator element is present
bool m_isSurfaceGenerationCase = false;
diff --git a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
index 765db5cb976..a1a99990d94 100644
--- a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
+++ b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp
@@ -123,6 +123,6 @@ void PerfectlyMatchedLayer::postInputInitialization()
}
-REGISTER_CATALOG_ENTRY( FieldSpecification, 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..39742654b15
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecification.cpp
@@ -0,0 +1,153 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * 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"
+#include "FieldSpecification.hpp"
+#include "FieldSpecificationFactory.hpp"
+#include "common/logger/Logger.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::initialConditionString(), &m_initialCondition ).
+ setApplyDefaultValue( 1 ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Boundary condition is applied as an initial condition." );
+
+ registerWrapper( viewKeyStruct::functionNamesString(), &m_functionNames ).
+ setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Name(s) of function(s) that specifies variation of the boundary condition." );
+
+ registerWrapper( viewKeyStruct::scalesString(), &m_scales ).
+ setApplyDefaultValue( 0.0 ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setSizedFromParent( 0 ).
+ setDescription( "Apply scaling factor(s) for the value(s) of the boundary condition." );
+
+ registerWrapper( viewKeyStruct::beginTimeString(), &m_beginTime ).
+ setApplyDefaultValue( -1.0e99 ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Time at which the boundary condition will start being applied." );
+
+ registerWrapper( viewKeyStruct::endTimeString(), &m_endTime ).
+ setApplyDefaultValue( 1.0e99 ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setDescription( "Time at which the boundary condition will stop being applied." );
+
+ registerWrapper( viewKeyStruct::errorSetModeString(), &m_emptySetErrorMode ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setApplyDefaultValue( FieldSpecification::SetErrorMode::error ).
+ setDescription( GEOS_FMT( "Set the log state when a “set” does not target any region\n"
+ "When set to \"{}\", no output.\n"
+ "When set to \"{}\", output a warning.\n"
+ "When set to \"{}\", output a throw.\n",
+ EnumStrings< FieldSpecification::SetErrorMode >::toString( FieldSpecification::SetErrorMode::silent ),
+ EnumStrings< FieldSpecification::SetErrorMode >::toString( FieldSpecification::SetErrorMode::warning ),
+ EnumStrings< FieldSpecification::SetErrorMode >::toString( FieldSpecification::SetErrorMode::error ) ));
+}
+
+
+PermeabilitySpecification::~PermeabilitySpecification()
+{}
+
+
+void PermeabilitySpecification::postInputInitialization()
+{
+ for( real64 scale : getScales() )
+ {
+ GEOS_THROW_IF( scale < 0,
+ GEOS_FMT( "Scale values for a permeability must be non-negative\nA value of {} was given in {} '{}'.",
+ scale, catalogName(), getName() ),
+ InputError,
+ getDataContext() );
+ }
+
+ GEOS_THROW_IF( !m_functionNames.empty() &&
+ m_functionNames.size() != 1 &&
+ m_functionNames.size() != static_cast< string_array::size_type >( m_scales.size() ),
+ GEOS_FMT ( "Size mismatch: '{}' has {} entries but '{}' has {}. "
+ "'{}' either must be empty, have a single entry, or be sized exactly like '{}'",
+ viewKeyStruct::functionNamesString(), m_functionNames.size(),
+ viewKeyStruct::scalesString(), m_scales.size(),
+ viewKeyStruct::functionNamesString(), viewKeyStruct::scalesString() ),
+ InputError,
+ getDataContext() );
+
+ GEOS_THROW_IF( m_beginTime > m_endTime,
+ GEOS_FMT( "{} ({}) must be less than {} ({}) in {} '{}'",
+ viewKeyStruct::beginTimeString(), m_beginTime,
+ viewKeyStruct::endTimeString(), m_endTime,
+ catalogName(), getName() ),
+ InputError,
+ getDataContext() );
+}
+
+
+REGISTER_CATALOG_ENTRY( FieldSpecificationABC, PermeabilitySpecification, string const &, Group * const )
+
+template<>
+void generateFieldSpecifications< PermeabilitySpecification >( PermeabilitySpecification const & ps,
+ dataRepository::Group & manager )
+{
+ for( string const & regionName : ps.getRegionNames() )
+ {
+ string const objectPath = "ElementRegions/" + regionName;
+
+ string const childName = ps.getName() + "_" + regionName;
+
+ FieldSpecification & fs = manager.registerGroup< FieldSpecification >( childName );
+ fs.setFieldName( ps.getFieldName() );
+ fs.setObjectPath( objectPath );
+ fs.initialCondition( ps.initialCondition() );
+ fs.setScales( ps.getScales() );
+ fs.setFunctionNames( ps.getFunctionNames() );
+ fs.setStartTime( ps.getStartTime() );
+ fs.setEndTime( ps.getEndTime() );
+ fs.setErrorSetMode( ps.getErrorSetMode() );
+
+ for( auto const & setName : ps.getSetNames() )
+ {
+ fs.addSetName( setName );
+ }
+ }
+}
+
+}
diff --git a/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp b/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp
new file mode 100644
index 00000000000..d64eb41dbf5
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/PermeabilitySpecification.hpp
@@ -0,0 +1,217 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * 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 "FieldSpecification.hpp"
+#include "FieldSpecificationABC.hpp"
+#include "FieldSpecificationFactory.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 initialCondition
+ constexpr static char const * initialConditionString() { return "initialCondition"; }
+ /// @return The key for functionNames
+ constexpr static char const * functionNamesString() { return "functionNames"; }
+ /// @return The key for scales
+ constexpr static char const * scalesString() { return "scales"; }
+ /// @return The key for beginTime
+ constexpr static char const * beginTimeString() { return "beginTime"; }
+ /// @return The key for endTime
+ constexpr static char const * endTimeString() { return "endTime"; }
+ /// @return The key errorSetMode
+ constexpr static char const * errorSetModeString() { return "errorSetMode"; }
+ };
+
+ /**
+ * Accessor
+ * @return const reference to m_functionNames
+ */
+ string_array const & getFunctionNames() const
+ { return m_functionNames; }
+
+ /**
+ * 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
+ */
+ array1d< real64 > getScales() const
+ { return m_scales; }
+
+ /**
+ * Accessor
+ * @return const m_initialCondition
+ */
+ int initialCondition() const
+ { return m_initialCondition; }
+
+ /**
+ * Accessor
+ * @return const m_beginTime
+ */
+ real64 getStartTime() const
+ { return m_beginTime; }
+
+ /**
+ * Accessor
+ * @return const m_endTime
+ */
+ real64 getEndTime() const
+ { return m_endTime; }
+
+ /**
+ * Accessor
+ * @return const m_emptySetErrorMode
+ */
+ FieldSpecification::SetErrorMode getErrorSetMode() const
+ { return m_emptySetErrorMode; }
+
+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;
+
+ /// Whether or not the boundary condition is an initial condition.
+ int m_initialCondition;
+
+ /// Name(s) of the function used to generate values for application.
+ string_array m_functionNames;
+
+ /// Scale factor(s) to use on the value of the boundary condition.
+ array1d< real64 > m_scales;
+
+ /// Time after which the bc is allowed to be applied
+ real64 m_beginTime;
+
+ /// Time after which the bc will no longer be applied.
+ real64 m_endTime;
+
+ /// Enum containing the possible output modes when an error occur
+ FieldSpecification::SetErrorMode m_emptySetErrorMode;
+
+};
+
+/// @copydoc geos::FieldSpecificationFactory::generateFieldSpecifications
+template<>
+void
+generateFieldSpecifications< PermeabilitySpecification >( PermeabilitySpecification const & specification,
+ dataRepository::Group & manager );
+
+}
+
+#endif //GEOS_FIELDSPECIFICATION_PERMEABILITYSPECIFICATION_HPP
diff --git a/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
index a702cd9bb9c..276960063b1 100644
--- a/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/SourceFluxBoundaryCondition.cpp
@@ -43,6 +43,6 @@ SourceFluxBoundaryCondition::SourceFluxBoundaryCondition( string const & name, G
FieldSpecification::viewKeyStruct::functionNamesString() ) );
}
-REGISTER_CATALOG_ENTRY( FieldSpecification, 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 30375f025c5..cfbe0f2c019 100644
--- a/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp
+++ b/src/coreComponents/fieldSpecification/TractionBoundaryCondition.cpp
@@ -440,7 +440,7 @@ void TractionBoundaryCondition::reinitScaleSet( FaceManager const & faceManager,
} );
}
-REGISTER_CATALOG_ENTRY( FieldSpecification, 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..1a5c370d17f
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/docs/PermeabilitySpecification.rst
@@ -0,0 +1,49 @@
+.. _PermeabilitySpecification:
+
+####################################################
+Permeability specification
+####################################################
+
+Overview
+======================
+
+**PermeabilitySpecification** is a XML tag that you can place in the **FieldSpecifications** block to describe a 3-axis permeability on one or more element regions.
+It is an higher-level component than **FieldSpecification**, specialized on permeability.
+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
+
+
+ ...
+
+ ...
+
diff --git a/src/coreComponents/fieldSpecification/unitTests/CMakeLists.txt b/src/coreComponents/fieldSpecification/unitTests/CMakeLists.txt
index 5a0f5dc9ad7..ea8999ddc4a 100644
--- a/src/coreComponents/fieldSpecification/unitTests/CMakeLists.txt
+++ b/src/coreComponents/fieldSpecification/unitTests/CMakeLists.txt
@@ -1,6 +1,7 @@
# Specify list of tests
set( gtest_geosx_tests
- testFieldSpecificationsEnums.cpp )
+ testFieldSpecificationsEnums.cpp
+ testPermeabilitySpecification.cpp )
# Basic dependency list: fieldSpecification library plus gtest and parallel deps
set( dependencyList ${parallelDeps} fieldSpecification gtest )
diff --git a/src/coreComponents/fieldSpecification/unitTests/testPermeabilitySpecification.cpp b/src/coreComponents/fieldSpecification/unitTests/testPermeabilitySpecification.cpp
new file mode 100644
index 00000000000..633af5cb2bb
--- /dev/null
+++ b/src/coreComponents/fieldSpecification/unitTests/testPermeabilitySpecification.cpp
@@ -0,0 +1,65 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * 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 "fieldSpecification/PermeabilitySpecification.hpp"
+#include "fieldSpecification/FieldSpecification.hpp"
+
+#include
+#include
+
+using namespace geos;
+using namespace dataRepository;
+
+namespace
+{
+
+void fillValidInput( PermeabilitySpecification & ps )
+{
+ ps.getReference< string_array >( PermeabilitySpecification::viewKeyStruct::setNamesString() ) = { "all" };
+ ps.getReference< string_array >( PermeabilitySpecification::viewKeyStruct::regionNamesString() ) = { "region1", "region2" };
+ ps.getReference< string >( PermeabilitySpecification::viewKeyStruct::fieldNameString() ) = "rockPerm_permeability";
+ array1d< real64 > & scales = ps.getReference< array1d< real64 > >( PermeabilitySpecification::viewKeyStruct::scalesString() );
+ scales.resize( 3 );
+ scales[0] = 9.869233e-16;
+ scales[1] = 9.869233e-16;
+ scales[2] = 9.869233e-16;
+}
+
+}
+
+TEST( PermeabilitySpecificationTest, ExpansionPropagatesAttributes )
+{
+ conduit::Node node;
+ Group rootGroup( "root", node );
+ PermeabilitySpecification ps( "perm", &rootGroup );
+
+ fillValidInput( ps );
+
+ EXPECT_NO_THROW( ps.postInputInitializationRecursive() );
+
+ Group manager( "FieldSpecifications", &rootGroup );
+ generateFieldSpecifications( ps, manager );
+
+ FieldSpecification const & fs = manager.getGroup< FieldSpecification >( "perm_region2" );
+
+ EXPECT_DOUBLE_EQ( fs.getScales()[0], 9.869233e-16 );
+}
+
+
+int main( int argc, char * * argv )
+{
+ ::testing::InitGoogleTest( &argc, argv );
+ return RUN_ALL_TESTS();
+}
diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd
index b6afd299b03..2b8333f33e9 100644
--- a/src/coreComponents/schema/schema.xsd
+++ b/src/coreComponents/schema/schema.xsd
@@ -212,6 +212,10 @@
+
+
+
+
@@ -1307,6 +1311,7 @@ Information output from lower logLevels is added with the desired log level
+
@@ -1529,6 +1534,35 @@ A set can be be defined by a 'Geometry' component, or correspond to imported set
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other
index 3c77f11a779..f63803784d3 100644
--- a/src/coreComponents/schema/schema.xsd.other
+++ b/src/coreComponents/schema/schema.xsd.other
@@ -297,6 +297,7 @@
+
@@ -336,6 +337,7 @@ A field can represent a physical variable. (pressure, temperature, global compos
+