diff --git a/examples/ObjectCatalog/Base.hpp b/examples/ObjectCatalog/Base.hpp index 2075058c05..c8e320afe4 100644 --- a/examples/ObjectCatalog/Base.hpp +++ b/examples/ObjectCatalog/Base.hpp @@ -5,7 +5,7 @@ * 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) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors * All rights reserved * @@ -46,7 +46,7 @@ class Parameter class Base { public: - Base( int junk, double const & junk2, Parameter& pbv ) + Base( int junk, double const & junk2, Parameter & pbv ) { GEOS_LOG( "calling Base constructor with arguments (" << junk << " " << junk2 << ")" ); } @@ -56,14 +56,20 @@ class Base GEOS_LOG( "calling Base destructor" ); } - using CatalogInterface = dataRepository::CatalogInterface< Base, int, double const &, Parameter& >; - static CatalogInterface::CatalogType& getCatalog() + using CatalogInterface = dataRepository::CatalogInterface< Base, int, double const &, Parameter & >; + static CatalogInterface::CatalogType & getCatalog() { static CatalogInterface::CatalogType catalog; return catalog; } virtual std::string const getName() const = 0; + + static DataContext const & getDataContext() + { + static DataFileContext const context = DataFileContext( "Base Test Class", __FILE__, __LINE__ ); + return context; + } }; #endif diff --git a/examples/ObjectCatalog/main.cpp b/examples/ObjectCatalog/main.cpp index 2a9ed5ba43..88c52c48d9 100644 --- a/examples/ObjectCatalog/main.cpp +++ b/examples/ObjectCatalog/main.cpp @@ -5,7 +5,7 @@ * 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) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors * All rights reserved * @@ -31,10 +31,14 @@ int main( int argc, char *argv[] ) GEOS_LOG( "Attempting to create a Derived1 object" ); - std::unique_ptr derived1 = Base::CatalogInterface::Factory( "derived1", junk, junk2, param ); + std::unique_ptr< Base > derived1 = Base::CatalogInterface::factory( "derived1", + Base::getDataContext(), + junk, junk2, param ); GEOS_LOG( "Attempting to create a Derived2 object" ); - std::unique_ptr derived2 = Base::CatalogInterface::Factory( "derived2", junk, junk3, param ); + std::unique_ptr< Base > derived2 = Base::CatalogInterface::factory( "derived2", + Base::getDataContext(), + junk, junk3, param ); - Base::CatalogInterface::catalog_cast( *(derived2.get())); + Base::CatalogInterface::catalog_cast< Derived1 >( *(derived2.get())); GEOS_LOG( "EXITING MAIN" ); } diff --git a/src/coreComponents/common/format/StringUtilities.hpp b/src/coreComponents/common/format/StringUtilities.hpp index 79b0333d0a..b79db4b116 100644 --- a/src/coreComponents/common/format/StringUtilities.hpp +++ b/src/coreComponents/common/format/StringUtilities.hpp @@ -88,7 +88,7 @@ string join( CONTAINER const & container, S const & delim = S() ) * @return a string containing input values concatenated with a delimiter */ template< typename IT, typename S, typename LAMBDA > -string joinLamda( IT first, IT last, S const & delim, LAMBDA formattingFunc ) +string joinLambda( IT first, IT last, S const & delim, LAMBDA formattingFunc ) { if( first == last ) { @@ -114,9 +114,9 @@ string joinLamda( IT first, IT last, S const & delim, LAMBDA formattingFunc ) * @return a string containing input values concatenated with a delimiter */ template< typename CONTAINER, typename S, typename LAMBDA > -string joinLamda( CONTAINER const & container, S const & delim, LAMBDA formattingFunc ) +string joinLambda( CONTAINER const & container, S const & delim, LAMBDA formattingFunc ) { - return joinLamda( std::begin( container ), std::end( container ), delim, formattingFunc ); + return joinLambda( std::begin( container ), std::end( container ), delim, formattingFunc ); } /** diff --git a/src/coreComponents/constitutive/ConstitutiveBase.cpp b/src/coreComponents/constitutive/ConstitutiveBase.cpp index 03bf6852ec..7323a64960 100644 --- a/src/coreComponents/constitutive/ConstitutiveBase.cpp +++ b/src/coreComponents/constitutive/ConstitutiveBase.cpp @@ -83,7 +83,8 @@ ConstitutiveBase::deliverClone( string const & name, Group * const parent ) const { std::unique_ptr< ConstitutiveBase > - newModel = ConstitutiveBase::CatalogInterface::factory( this->getCatalogName(), name, parent ); + newModel = ConstitutiveBase::CatalogInterface::factory( this->getCatalogName(), getDataContext(), + name, parent ); newModel->forWrappers( [&]( WrapperBase & wrapper ) { diff --git a/src/coreComponents/constitutive/ConstitutiveManager.cpp b/src/coreComponents/constitutive/ConstitutiveManager.cpp index 3babd88203..913f089897 100644 --- a/src/coreComponents/constitutive/ConstitutiveManager.cpp +++ b/src/coreComponents/constitutive/ConstitutiveManager.cpp @@ -44,7 +44,8 @@ ConstitutiveManager::~ConstitutiveManager() Group * ConstitutiveManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< ConstitutiveBase > material = ConstitutiveBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< ConstitutiveBase > material = + ConstitutiveBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return ®isterGroup< ConstitutiveBase >( childName, std::move( material ) ); } diff --git a/src/coreComponents/dataRepository/DataContext.cpp b/src/coreComponents/dataRepository/DataContext.cpp index 87e9f79175..d34ab4b72c 100644 --- a/src/coreComponents/dataRepository/DataContext.cpp +++ b/src/coreComponents/dataRepository/DataContext.cpp @@ -25,7 +25,7 @@ namespace dataRepository { -DataContext::DataContext( string const & targetName ): +DataContext::DataContext( string_view targetName ): m_targetName( targetName ) {} @@ -35,12 +35,12 @@ std::ostream & operator<<( std::ostream & os, DataContext const & ctx ) return os; } -DataContext::ToStringInfo::ToStringInfo( string const & targetName, string const & filePath, size_t line ): +DataContext::ToStringInfo::ToStringInfo( string_view targetName, string_view filePath, size_t line ): m_targetName( targetName ), m_filePath( filePath ), m_line( line ) {} -DataContext::ToStringInfo::ToStringInfo( string const & targetName ): +DataContext::ToStringInfo::ToStringInfo( string_view targetName ): m_targetName( targetName ) {} @@ -83,6 +83,15 @@ DataFileContext::DataFileContext( xmlWrapper::xmlNode const & targetNode, m_offset( attPos.offset ) {} +DataFileContext::DataFileContext( string_view targetName, string_view file, size_t line ): + DataContext( targetName ), + m_typeName( "C++ Source File" ), + m_filePath( file ), + m_line( line ), + m_offsetInLine( 0 ), + m_offset( 0 ) +{} + string DataFileContext::toString() const { if( m_line != xmlWrapper::xmlDocument::npos ) @@ -95,7 +104,7 @@ string DataFileContext::toString() const } else { - return GEOS_FMT( "{} (Source file not found)", m_targetName ); + return GEOS_FMT( "{} ({})", m_targetName, ( m_filePath.empty() ? "Source file not found" : m_filePath ) ); } } diff --git a/src/coreComponents/dataRepository/DataContext.hpp b/src/coreComponents/dataRepository/DataContext.hpp index 46daeb3850..ee3abd0f1c 100644 --- a/src/coreComponents/dataRepository/DataContext.hpp +++ b/src/coreComponents/dataRepository/DataContext.hpp @@ -47,7 +47,7 @@ class DataContext * @brief Construct a new DataContext object. * @param targetName the target object name */ - DataContext( string const & targetName ); + DataContext( string_view targetName ); /** * @brief Destroy the DataContext object @@ -95,12 +95,12 @@ class DataContext * @param filePath the input file path where the target is declared. * @param line the line in the file where the target is declared. */ - ToStringInfo( string const & targetName, string const & filePath, size_t line ); + ToStringInfo( string_view targetName, string_view filePath, size_t line ); /** * @brief Construct a new ToStringInfo object from a DataContext that has no input file info. * @param targetName the target name. */ - ToStringInfo( string const & targetName ); + ToStringInfo( string_view targetName ); /** * @return true if a location has been found to declare the target in an input file. */ @@ -142,6 +142,14 @@ class DataFileContext final : public DataContext DataFileContext( xmlWrapper::xmlNode const & targetNode, xmlWrapper::xmlAttribute const & att, xmlWrapper::xmlAttributePos const & attPos ); + /** + * @brief Constructs the file context of a Group from a C++ source file. + * @param targetName The name of the target Group. + * @param file The name of the source file. + * @param line The line number in the source file. + */ + DataFileContext( string_view targetName, string_view file, size_t line ); + /** * @return the target object name followed by the the file and line declaring it. */ diff --git a/src/coreComponents/dataRepository/Group.cpp b/src/coreComponents/dataRepository/Group.cpp index 440178c2a7..8665b5aa9c 100644 --- a/src/coreComponents/dataRepository/Group.cpp +++ b/src/coreComponents/dataRepository/Group.cpp @@ -135,18 +135,64 @@ string Group::getPath() const return noProblem.empty() ? "/" : noProblem; } +string Group::processInputName( xmlWrapper::xmlNode const & targetNode, + xmlWrapper::xmlNodePos const & targetNodePos, + string_view parentNodeName, + xmlWrapper::xmlNodePos const & parentNodePos, + std::set< string > & siblingNames ) +{ + GEOS_THROW_IF( targetNode.type() != xmlWrapper::xmlNodeType::node_element, + GEOS_FMT( "Error in node named \"{}\" ({}): GEOS XML nodes cannot contain " + "text data nor anything but XML nodes.\nErroneous content: \"{}\"\n", + parentNodeName, parentNodePos.toString(), + stringutilities::trimSpaces( targetNode.value() ) ), + InputError ); + + string targetNodeName; + try + { // read & validate the name attribute + xmlWrapper::readAttributeAsType( targetNodeName, "name", + rtTypes::getTypeRegex< string >( rtTypes::CustomTypes::groupName ), + targetNode, string( "" ) ); + } catch( std::exception const & ex ) + { + xmlWrapper::processInputException( ex, "name", targetNode, targetNodePos ); + } + + if( targetNodeName.empty() ) + { // if there is no name attribute, we use the node tag as a node name + targetNodeName = targetNode.name(); + } + else + { // Make sure names are not duplicated by checking all previous siblings + GEOS_THROW_IF( siblingNames.count( targetNodeName ) != 0, + GEOS_FMT( "Error at node named \"{}\" ({}): " + "An XML block cannot contain children with duplicated names.\n", + targetNodeName, targetNodePos.toString() ), + InputError ); + siblingNames.insert( targetNodeName ); + } + + return targetNodeName; +} + void Group::processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, xmlWrapper::xmlNode & targetNode ) { - xmlWrapper::xmlNodePos nodePos = xmlDocument.getNodePosition( targetNode ); - processInputFileRecursive( xmlDocument, targetNode, nodePos ); + xmlWrapper::xmlNodePos targetNodePos = xmlDocument.getNodePosition( targetNode ); + processInputFileRecursive( xmlDocument, targetNode, targetNodePos ); } void Group::processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, xmlWrapper::xmlNode & targetNode, - xmlWrapper::xmlNodePos const & nodePos ) + xmlWrapper::xmlNodePos const & targetNodePos ) { xmlDocument.addIncludedXML( targetNode ); + if( targetNodePos.isFound() ) + { + m_dataContext = std::make_unique< DataFileContext >( targetNode, targetNodePos ); + } + // Handle the case where the node was imported from a different input file // Set the path prefix to make sure all relative Path variables are interpreted correctly string const oldPrefix = std::string( Path::getPathPrefix() ); @@ -157,40 +203,12 @@ void Group::processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, } // Loop over the child nodes of the targetNode - array1d< string > childNames; + std::set< string > childNames; for( xmlWrapper::xmlNode childNode : targetNode.children() ) { xmlWrapper::xmlNodePos childNodePos = xmlDocument.getNodePosition( childNode ); - - // Get the child tag and name - string childName; - - try - { - xmlWrapper::readAttributeAsType( childName, "name", - rtTypes::getTypeRegex< string >( rtTypes::CustomTypes::groupName ), - childNode, string( "" ) ); - } catch( std::exception const & ex ) - { - xmlWrapper::processInputException( ex, "name", childNode, childNodePos ); - } - - if( childName.empty() ) - { - childName = childNode.name(); - } - else - { - // Make sure child names are not duplicated - GEOS_ERROR_IF( std::find( childNames.begin(), childNames.end(), childName ) != childNames.end(), - GEOS_FMT( "Error: An XML block cannot contain children with duplicated names.\n" - "Error detected at node {} with name = {} ({}:l.{})", - childNode.path(), childName, xmlDocument.getFilePath(), - xmlDocument.getNodePosition( childNode ).line ) ); - - childNames.emplace_back( childName ); - } - + string const childName = processInputName( childNode, childNodePos, + getName(), targetNodePos, childNames ); // Create children Group * newChild = createChild( childNode.name(), childName ); if( newChild == nullptr ) @@ -203,7 +221,7 @@ void Group::processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, } } - processInputFile( targetNode, nodePos ); + processInputFile( targetNode, targetNodePos ); // Restore original prefix once the node is processed Path::setPathPrefix( oldPrefix ); @@ -212,12 +230,6 @@ void Group::processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, void Group::processInputFile( xmlWrapper::xmlNode const & targetNode, xmlWrapper::xmlNodePos const & nodePos ) { - if( nodePos.isFound() ) - { - m_dataContext = std::make_unique< DataFileContext >( targetNode, nodePos ); - } - - std::set< string > processedAttributes; for( std::pair< string const, WrapperBase * > & pair : m_wrappers ) { @@ -233,10 +245,10 @@ void Group::processInputFile( xmlWrapper::xmlNode const & targetNode, if( !xmlWrapper::isFileMetadataAttribute( attributeName ) ) { GEOS_THROW_IF( processedAttributes.count( attributeName ) == 0, - GEOS_FMT( "XML Node at '{}' with name={} contains unused attribute '{}'.\n" + GEOS_FMT( "Error in {}: XML Node at '{}' contains unused attribute '{}'.\n" "Valid attributes are:\n{}\nFor more details, please refer to documentation at:\n" "http://geosx-geosx.readthedocs-hosted.com/en/latest/docs/sphinx/userGuide/Index.html", - targetNode.path(), m_dataContext->toString(), attributeName, + getDataContext(), targetNode.path(), attributeName, dumpInputOptions() ), InputError ); } @@ -264,11 +276,10 @@ void Group::registerDataOnMeshRecursive( Group & meshBodies ) Group * Group::createChild( string const & childKey, string const & childName ) { - GEOS_ERROR_IF( !(CatalogInterface::hasKeyName( childKey )), - "KeyName ("<) - * - * @tparam T The type of the Group to add/register. This should be a type that derives from Group. - * @tparam TBASE The type whose type catalog will be used to look up the new sub-group type - * @param[in] name The name of the group to use as a string key. - * @param[in] catalogName The catalog name of the new type. - * @return A pointer to the newly registered Group. - * - * Creates and registers a Group or class derived from Group as a subgroup of this Group. - */ - template< typename T = Group, typename TBASE = Group > - T & registerGroup( string const & name, string const & catalogName ) - { - std::unique_ptr< TBASE > newGroup = TBASE::CatalogInterface::Factory( catalogName, name, this ); - return registerGroup< T >( name, std::move( newGroup ) ); - } - /** * @brief Removes a child group from this group. * @param name the name of the child group to remove from this group. @@ -769,6 +751,26 @@ class Group */ void postRestartInitializationRecursive(); + /** + * @return The validated name for a given Group from its xml value: If the node has a "name" + * attribute, it is validated after the `groupName` rtType regex, and its value is + * returned. Else if the Group name is not "Required", the node tag name is used. + * @param targetNode The XML node whose name is to be processed. It throws if not of element type. + * @param targetNodePos The position of the target node within the XML document. + * @param parentNodeName The name of the parent node, used for error reporting. + * @param parentNodePos The position of the parent node, used for error reporting. + * @param siblingNames A set containing the names of sibling nodes (to verify that there are no + * duplicates). The function will populate this set if the attribute name is + * used and if no error is found. + * @throws InputError if the node type is not an xml element or if there are duplicate names + * among xml siblings. + */ + static string processInputName( xmlWrapper::xmlNode const & targetNode, + xmlWrapper::xmlNodePos const & targetNodePos, + string_view parentNodeName, + xmlWrapper::xmlNodePos const & parentNodePos, + std::set< string > & siblingNames ); + /** * @brief Recursively read values using ProcessInputFile() from the input * file and put them into the wrapped values for this group. @@ -783,11 +785,11 @@ class Group * but allow to reuse an existing xmlNodePos. * @param[in] xmlDocument the XML document that contains the targetNode. * @param[in] targetNode the XML node that to extract input values from. - * @param[in] nodePos the target node position, typically obtained with xmlDocument::getNodePosition(). + * @param[in] targetNodePos the target node position, typically obtained with xmlDocument::getNodePosition(). */ void processInputFileRecursive( xmlWrapper::xmlDocument & xmlDocument, xmlWrapper::xmlNode & targetNode, - xmlWrapper::xmlNodePos const & nodePos ); + xmlWrapper::xmlNodePos const & targetNodePos ); /** * @brief Recursively call postInputInitialization() to apply post processing after diff --git a/src/coreComponents/dataRepository/GroupContext.cpp b/src/coreComponents/dataRepository/GroupContext.cpp index d21771cfbd..c60880bd76 100644 --- a/src/coreComponents/dataRepository/GroupContext.cpp +++ b/src/coreComponents/dataRepository/GroupContext.cpp @@ -25,7 +25,7 @@ namespace dataRepository { -GroupContext::GroupContext( Group & group, string const & objectName ): +GroupContext::GroupContext( Group & group, string_view objectName ): DataContext( objectName ), m_group( group ) {} diff --git a/src/coreComponents/dataRepository/GroupContext.hpp b/src/coreComponents/dataRepository/GroupContext.hpp index 476540f98e..166543b883 100644 --- a/src/coreComponents/dataRepository/GroupContext.hpp +++ b/src/coreComponents/dataRepository/GroupContext.hpp @@ -57,7 +57,7 @@ class GroupContext : public DataContext * @param group The reference to the Group related to this GroupContext. * @param objectName Target object name. */ - GroupContext( Group & group, string const & objectName ); + GroupContext( Group & group, string_view objectName ); /// The reference to the Group related to this GroupContext. Group & m_group; diff --git a/src/coreComponents/dataRepository/ObjectCatalog.hpp b/src/coreComponents/dataRepository/ObjectCatalog.hpp index dbf089033a..2fd0762c97 100644 --- a/src/coreComponents/dataRepository/ObjectCatalog.hpp +++ b/src/coreComponents/dataRepository/ObjectCatalog.hpp @@ -30,6 +30,7 @@ #include "common/logger/Logger.hpp" #include "common/format/StringUtilities.hpp" #include "LvArray/src/system.hpp" +#include "DataContext.hpp" #include #include @@ -171,39 +172,48 @@ class CatalogInterface /** * @brief Static method to create a new object that derives from BASETYPE * @param[in] objectTypeName the key to the catalog entry that is able to create the correct type. + * @param context The data context of the Group for which we attempt to create a sub-group. * @param args these are the arguments to the constructor of the target type * @return passes a unique_ptr to the newly allocated class. - * - * @note The simulation is killed if the builder is not found. + * @note Generate a fatal error: + * - if the object type to create is not found in this Catalog, + * - if the builder is not found. */ //START_SPHINX_2 static std::unique_ptr< BASETYPE > factory( std::string const & objectTypeName, + DataContext const & context, ARGS... args ) { - // We stop the simulation if the product is not found - if( !hasKeyName( objectTypeName ) ) - { - std::list< typename CatalogType::key_type > keys = getKeys(); - string const tmp = stringutilities::join( keys.cbegin(), keys.cend(), ",\n" ); - - string errorMsg = "Could not find keyword \"" + objectTypeName + "\" in this context. "; - errorMsg += "Please be sure that all your keywords are properly spelled or that input file parameters have not changed.\n"; - errorMsg += "All available keys are: [\n" + tmp + "\n]"; - GEOS_ERROR( errorMsg ); - } + // We stop the simulation if the type to create is not found + GEOS_ERROR_IF( !hasKeyName( objectTypeName ), unknownTypeError( objectTypeName, context, getKeys() ) ); // We also stop the simulation if the builder is not here. CatalogInterface< BASETYPE, ARGS... > const * builder = getCatalog().at( objectTypeName ).get(); - if( builder == nullptr ) - { - const string errorMsg = "\"" + objectTypeName + "\" could be found. But the builder is invalid.\n"; - GEOS_ERROR( errorMsg ); - } + GEOS_ERROR_IF( builder == nullptr, + GEOS_FMT( "Type \"{}\" is valid in {}, but the builder is invalid.", + objectTypeName, context ) ); return builder->allocate( args ... ); } //STOP_SPHINX + /** + * @return Generates a formatted error message for an unknown type for a catalog. + * @param objectTypeName The name of the object type that is invalid. + * @param context The data context of the Group for which the erroneous type creation was attempted. + * @param allowedKeys A container of allowed keys, which will be listed in the error message. + * @tparam KEYS_CONTAINER_T A container type holding the allowed keys. + */ + template< typename KEYS_CONTAINER_T > + static string unknownTypeError( string const & objectTypeName, DataContext const & context, + KEYS_CONTAINER_T const & allowedKeys ) + { + return GEOS_FMT( "The tag \"{}\" is invalid within {}. Please verify the keywords spelling and that " + "input file parameters have not changed.\n" + "All available tags are: {}\n", + objectTypeName, context, stringutilities::join( allowedKeys, ", " ) ); + } + /** * @brief Downcast base type reference to derived type * @tparam TYPE type to cast to @@ -303,7 +313,7 @@ class CatalogEntry final : public CatalogInterface< BASETYPE, ARGS... > */ CatalogEntry & operator=( CatalogEntry && source ) { - CatalogInterface< BASETYPE, ARGS... >::operator=( std::move(source)); + CatalogInterface< BASETYPE, ARGS... >::operator=( std::move( source )); } /** @@ -312,7 +322,7 @@ class CatalogEntry final : public CatalogInterface< BASETYPE, ARGS... > * @return a unique_ptr to the newly allocated class. */ //START_SPHINX_4 - virtual std::unique_ptr< BASETYPE > allocate( ARGS... args ) const override + virtual std::unique_ptr< BASETYPE > allocate( ARGS ... args ) const override { #if OBJECTCATALOGVERBOSE > 0 GEOS_LOG( "Creating type " << LvArray::system::demangle( typeid(TYPE).name()) @@ -589,7 +599,7 @@ class CatalogEntry< BASETYPE, TYPE > final : public CatalogInterface< BASETYPE > */ CatalogEntry & operator=( CatalogEntry && source ) { - CatalogInterface< BASETYPE >::operator=( std::move(source)); + CatalogInterface< BASETYPE >::operator=( std::move( source )); } /** diff --git a/src/coreComponents/dataRepository/xmlWrapper.cpp b/src/coreComponents/dataRepository/xmlWrapper.cpp index e0ada302c4..c84439c874 100644 --- a/src/coreComponents/dataRepository/xmlWrapper.cpp +++ b/src/coreComponents/dataRepository/xmlWrapper.cpp @@ -32,18 +32,29 @@ using namespace dataRepository; namespace xmlWrapper { -void validateString( string const & value, Regex const & regex ) +void validateString( string const & value, const Regex & regex ) { - std::smatch m; - bool inputValidated = std::regex_match( value, m, std::regex( regex.m_regexStr ) ); - if( !inputValidated ) + std::regex regexInstance{ regex.m_regexStr }; + // if validation fails, let's try to find the error start & end to underline it. If it fails, underline the whole message. + if( !std::regex_match( value, regexInstance )) { - ptrdiff_t errorId = ( m.size()>0 && m.position( 0 )==0 ) ? m.length() : 0; + std::smatch m; + std::regex_search( value, m, regexInstance ); + ptrdiff_t const errorStart = ( m.size()>0 && m.position( 0 )==0 ) ? m.length() : 0; + + size_t errorLength; + for( errorLength = 1; errorStart + errorLength < value.length(); ++errorLength ) + { + if( std::regex_match( value.substr( errorStart + errorLength, 1 ), regexInstance ) ) + break; + } + + string const underline = string( errorStart, ' ' ) + string( errorLength, '^' ); GEOS_THROW( GEOS_FMT( "Input string validation failed at:\n" " \"{}\"\n" - " {:>{}}\n" + " {}\n" " Expected format: {}", - value, '^', errorId+1, regex.m_formatDescription ), + value, underline, regex.m_formatDescription ), InputError ); } } diff --git a/src/coreComponents/discretizationMethods/NumericalMethodsManager.cpp b/src/coreComponents/discretizationMethods/NumericalMethodsManager.cpp index 6e4fb3c5cf..f9dbbb06bc 100644 --- a/src/coreComponents/discretizationMethods/NumericalMethodsManager.cpp +++ b/src/coreComponents/discretizationMethods/NumericalMethodsManager.cpp @@ -41,6 +41,7 @@ NumericalMethodsManager::~NumericalMethodsManager() Group * NumericalMethodsManager::createChild( string const & GEOS_UNUSED_PARAM( childKey ), string const & GEOS_UNUSED_PARAM( childName ) ) { + // Unused as all children are created within the constructor return nullptr; } diff --git a/src/coreComponents/events/EventBase.cpp b/src/coreComponents/events/EventBase.cpp index 6212dc89d6..52b3c386c2 100644 --- a/src/coreComponents/events/EventBase.cpp +++ b/src/coreComponents/events/EventBase.cpp @@ -123,7 +123,8 @@ EventBase::CatalogInterface::CatalogType & EventBase::getCatalog() Group * EventBase::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< EventBase > event = EventBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< EventBase > event = + EventBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< EventBase >( childName, std::move( event ) ); } diff --git a/src/coreComponents/events/EventManager.cpp b/src/coreComponents/events/EventManager.cpp index 69c3a46dd9..3f709bce94 100644 --- a/src/coreComponents/events/EventManager.cpp +++ b/src/coreComponents/events/EventManager.cpp @@ -94,7 +94,8 @@ EventManager::~EventManager() Group * EventManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< EventBase > event = EventBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< EventBase > event = + EventBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< EventBase >( childName, std::move( event ) ); } diff --git a/src/coreComponents/events/tasks/TasksManager.cpp b/src/coreComponents/events/tasks/TasksManager.cpp index 9f95aefb2a..7dfec005c6 100644 --- a/src/coreComponents/events/tasks/TasksManager.cpp +++ b/src/coreComponents/events/tasks/TasksManager.cpp @@ -39,7 +39,8 @@ TasksManager::~TasksManager() Group * TasksManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< TaskBase > task = TaskBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< TaskBase > task = + TaskBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< TaskBase >( childName, std::move( task ) ); } diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp index 155596304d..94bbe9ea44 100644 --- a/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp +++ b/src/coreComponents/fieldSpecification/FieldSpecificationManager.cpp @@ -52,7 +52,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, childName, this ); + std::unique_ptr< FieldSpecificationBase > bc = + FieldSpecificationBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup( childName, std::move( bc ) ); } diff --git a/src/coreComponents/fileIO/Outputs/OutputManager.cpp b/src/coreComponents/fileIO/Outputs/OutputManager.cpp index 42ea71af77..7fcafb8aa9 100644 --- a/src/coreComponents/fileIO/Outputs/OutputManager.cpp +++ b/src/coreComponents/fileIO/Outputs/OutputManager.cpp @@ -40,7 +40,8 @@ OutputManager::~OutputManager() Group * OutputManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< OutputBase > output = OutputBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< OutputBase > output = + OutputBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< OutputBase >( childName, std::move( output ) ); } diff --git a/src/coreComponents/finiteElement/FiniteElementDiscretizationManager.cpp b/src/coreComponents/finiteElement/FiniteElementDiscretizationManager.cpp index 8bd43f0cda..9bc4e70c5c 100644 --- a/src/coreComponents/finiteElement/FiniteElementDiscretizationManager.cpp +++ b/src/coreComponents/finiteElement/FiniteElementDiscretizationManager.cpp @@ -41,7 +41,8 @@ Group * FiniteElementDiscretizationManager::createChild( string const & childKey { // These objects should probably not be registered on managed group... GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< Group > fem = Group::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< Group > fem = + Group::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup( childName, std::move( fem ) ); } diff --git a/src/coreComponents/finiteVolume/FiniteVolumeManager.cpp b/src/coreComponents/finiteVolume/FiniteVolumeManager.cpp index 500d1da5ec..b4329194c6 100644 --- a/src/coreComponents/finiteVolume/FiniteVolumeManager.cpp +++ b/src/coreComponents/finiteVolume/FiniteVolumeManager.cpp @@ -50,7 +50,8 @@ Group * FiniteVolumeManager::createChild( string const & childKey, string const } else { - std::unique_ptr< FluxApproximationBase > approx = FluxApproximationBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< FluxApproximationBase > approx = FluxApproximationBase::CatalogInterface::factory( childKey, getDataContext(), + childName, this ); return &this->registerGroup< FluxApproximationBase >( childName, std::move( approx )); } } diff --git a/src/coreComponents/functions/FunctionManager.cpp b/src/coreComponents/functions/FunctionManager.cpp index 0cd5a92ba9..2f8425beb9 100644 --- a/src/coreComponents/functions/FunctionManager.cpp +++ b/src/coreComponents/functions/FunctionManager.cpp @@ -54,7 +54,8 @@ Group * FunctionManager::createChild( string const & functionCatalogKey, string const & functionName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), functionCatalogKey, functionName ) ); - std::unique_ptr< FunctionBase > function = FunctionBase::CatalogInterface::factory( functionCatalogKey, functionName, this ); + std::unique_ptr< FunctionBase > function = + FunctionBase::CatalogInterface::factory( functionCatalogKey, getDataContext(), functionName, this ); return &this->registerGroup< FunctionBase >( functionName, std::move( function ) ); } diff --git a/src/coreComponents/mainInterface/ProblemManager.cpp b/src/coreComponents/mainInterface/ProblemManager.cpp index 652c1d3193..890f550c75 100644 --- a/src/coreComponents/mainInterface/ProblemManager.cpp +++ b/src/coreComponents/mainInterface/ProblemManager.cpp @@ -159,7 +159,10 @@ ProblemManager::~ProblemManager() Group * ProblemManager::createChild( string const & GEOS_UNUSED_PARAM( childKey ), string const & GEOS_UNUSED_PARAM( childName ) ) -{ return nullptr; } +{ + // Unused as all children are created within the constructor + return nullptr; +} void ProblemManager::problemSetup() @@ -455,52 +458,44 @@ void ProblemManager::parseXMLDocument( xmlWrapper::xmlDocument & xmlDocument ) meshManager.generateMeshLevels( domain ); Group & meshBodies = domain.getMeshBodies(); - // Parse element regions - xmlWrapper::xmlNode elementRegionsNode = xmlProblemNode.child( MeshLevel::groupStructKeys::elemManagerString() ); - - for( xmlWrapper::xmlNode regionNode : elementRegionsNode.children() ) + auto parseRegions = [&]( string_view regionManagerKey, bool const hasParticles ) { - string const regionName = regionNode.attribute( "name" ).value(); - try + xmlWrapper::xmlNode regionsNode = xmlProblemNode.child( regionManagerKey.data() ); + xmlWrapper::xmlNodePos regionsNodePos = xmlDocument.getNodePosition( regionsNode ); + std::set< string > regionNames; + + for( xmlWrapper::xmlNode regionNode : regionsNode.children() ) { - string const - regionMeshBodyName = ElementRegionBase::verifyMeshBodyName( meshBodies, - regionNode.attribute( "meshBody" ).value() ); + auto const regionNodePos = xmlDocument.getNodePosition( regionNode ); + string const regionName = Group::processInputName( regionNode, regionNodePos, + regionsNode.name(), regionsNodePos, regionNames ); + try + { + string const regionMeshBodyName = + ElementRegionBase::verifyMeshBodyName( meshBodies, + regionNode.attribute( "meshBody" ).value() ); - MeshBody & meshBody = domain.getMeshBody( regionMeshBodyName ); - meshBody.forMeshLevels( [&]( MeshLevel & meshLevel ) + MeshBody & meshBody = domain.getMeshBody( regionMeshBodyName ); + meshBody.setHasParticles( hasParticles ); + meshBody.forMeshLevels( [&]( MeshLevel & meshLevel ) + { + ObjectManagerBase & elementManager = hasParticles ? + static_cast< ObjectManagerBase & >( meshLevel.getParticleManager() ): + static_cast< ObjectManagerBase & >( meshLevel.getElemManager() ); + Group * newRegion = elementManager.createChild( regionNode.name(), regionName ); + newRegion->processInputFileRecursive( xmlDocument, regionNode ); + } ); + } + catch( InputError const & e ) { - ElementRegionManager & elementManager = meshLevel.getElemManager(); - Group * newRegion = elementManager.createChild( regionNode.name(), regionName ); - newRegion->processInputFileRecursive( xmlDocument, regionNode ); - } ); - } - catch( InputError const & e ) - { - string const nodePosString = xmlDocument.getNodePosition( regionNode ).toString(); - throw InputError( e, "Error while parsing region " + regionName + " (" + nodePosString + "):\n" ); + throw InputError( e, GEOS_FMT( "Error while parsing region {} ({}):\n", + regionName, regionNodePos.toString() ) ); + } } - } + }; - // Parse particle regions - xmlWrapper::xmlNode particleRegionsNode = xmlProblemNode.child( MeshLevel::groupStructKeys::particleManagerString() ); - - for( xmlWrapper::xmlNode regionNode : particleRegionsNode.children() ) - { - string const regionName = regionNode.attribute( "name" ).value(); - string const - regionMeshBodyName = ElementRegionBase::verifyMeshBodyName( meshBodies, - regionNode.attribute( "meshBody" ).value() ); - - MeshBody & meshBody = domain.getMeshBody( regionMeshBodyName ); - meshBody.setHasParticles( true ); - meshBody.forMeshLevels( [&]( MeshLevel & meshLevel ) - { - ParticleManager & particleManager = meshLevel.getParticleManager(); - Group * newRegion = particleManager.createChild( regionNode.name(), regionName ); - newRegion->processInputFileRecursive( xmlDocument, regionNode ); - } ); - } + parseRegions( MeshLevel::groupStructKeys::elemManagerString(), false ); + parseRegions( MeshLevel::groupStructKeys::particleManagerString(), true ); } } diff --git a/src/coreComponents/mesh/CellElementRegionSelector.cpp b/src/coreComponents/mesh/CellElementRegionSelector.cpp index f5bbc00611..f6106a88a2 100644 --- a/src/coreComponents/mesh/CellElementRegionSelector.cpp +++ b/src/coreComponents/mesh/CellElementRegionSelector.cpp @@ -67,10 +67,10 @@ CellElementRegionSelector::getMatchingCellblocks( CellElementRegion const & regi "Available cellBlock list: {{ {} }}\nAvailable region attribute list: {{ {} }}", region.getWrapperDataContext( ViewKeys::sourceCellBlockNamesString() ), matchPattern, - stringutilities::joinLamda( m_regionAttributesOwners, ", ", - []( auto pair ) { return pair->first; } ), - stringutilities::joinLamda( m_cellBlocksOwners, ", ", - []( auto pair ) { return pair->first; } ) ), + stringutilities::joinLambda( m_regionAttributesOwners, ", ", + []( auto pair ) { return pair->first; } ), + stringutilities::joinLambda( m_cellBlocksOwners, ", ", + []( auto pair ) { return pair->first; } ) ), InputError ); return matchedCellBlocks; } @@ -86,8 +86,8 @@ CellElementRegionSelector::verifyRequestedCellBlocks( CellElementRegion const & GEOS_FMT( "{}: No cellBlock named '{}'.\nAvailable cellBlock list: {{ {} }}", region.getWrapperDataContext( ViewKeys::sourceCellBlockNamesString() ), requestedCellBlockName, - stringutilities::joinLamda( m_cellBlocksOwners, ", ", - []( auto pair ) { return pair->first; } ) ), + stringutilities::joinLambda( m_cellBlocksOwners, ", ", + []( auto pair ) { return pair->first; } ) ), InputError ); } } @@ -162,7 +162,7 @@ void CellElementRegionSelector::checkSelectionConsistency() const multipleRefsErrors.push_back( GEOS_FMT( "The {} '{}' has been referenced in multiple {}:\n{}", qualifierType, qualifier, CellElementRegion::catalogName(), - stringutilities::joinLamda( owningRegions, '\n', getRegionStr ) ) ); + stringutilities::joinLambda( owningRegions, '\n', getRegionStr ) ) ); } } GEOS_THROW_IF( !multipleRefsErrors.empty(), stringutilities::join( multipleRefsErrors, "\n\n" ), InputError ); diff --git a/src/coreComponents/mesh/ElementRegionManager.cpp b/src/coreComponents/mesh/ElementRegionManager.cpp index 18da04ec06..2652103216 100644 --- a/src/coreComponents/mesh/ElementRegionManager.cpp +++ b/src/coreComponents/mesh/ElementRegionManager.cpp @@ -69,31 +69,32 @@ void ElementRegionManager::setMaxGlobalIndex() m_maxGlobalIndex = MpiWrapper::max( m_localMaxGlobalIndex, MPI_COMM_GEOS ); } - +auto const & getUserAvailableKeys() +{ + static std::set< string > keys = { + CellElementRegion::catalogName(), + WellElementRegion::catalogName(), + SurfaceElementRegion::catalogName(), + }; + return keys; +} Group * ElementRegionManager::createChild( string const & childKey, string const & childName ) { - GEOS_ERROR_IF( !(CatalogInterface::hasKeyName( childKey )), - "KeyName ("<getGroup( ElementRegionManager::groupKeyStruct::elementRegionsGroup() ); return &elementRegions.registerGroup( childName, - CatalogInterface::factory( childKey, childName, &elementRegions ) ); + CatalogInterface::factory( childKey, getDataContext(), + childName, &elementRegions ) ); } void ElementRegionManager::expandObjectCatalogs() { - ObjectManagerBase::CatalogInterface::CatalogType const & catalog = ObjectManagerBase::getCatalog(); - for( ObjectManagerBase::CatalogInterface::CatalogType::const_iterator iter = catalog.begin(); - iter!=catalog.end(); - ++iter ) + for( string const & key : getUserAvailableKeys() ) { - string const key = iter->first; - if( key.find( "ElementRegion" ) != string::npos ) - { - this->createChild( key, key ); - } + this->createChild( key, key ); } } diff --git a/src/coreComponents/mesh/ExternalDataSourceBase.cpp b/src/coreComponents/mesh/ExternalDataSourceBase.cpp index 157fe3de31..9c1285764d 100644 --- a/src/coreComponents/mesh/ExternalDataSourceBase.cpp +++ b/src/coreComponents/mesh/ExternalDataSourceBase.cpp @@ -28,8 +28,9 @@ ExternalDataSourceBase::ExternalDataSourceBase( string const & name, Group * con Group * ExternalDataSourceBase::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< ExternalDataSourceBase > event = ExternalDataSourceBase::CatalogInterface::factory( childKey, childName, this ); - return &this->registerGroup< ExternalDataSourceBase >( childName, std::move( event ) ); + std::unique_ptr< ExternalDataSourceBase > event = + ExternalDataSourceBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); + return &this->registerGroup( childName, std::move( event ) ); } void ExternalDataSourceBase::expandObjectCatalogs() diff --git a/src/coreComponents/mesh/ExternalDataSourceManager.cpp b/src/coreComponents/mesh/ExternalDataSourceManager.cpp index 8a22203af8..969ab7a043 100644 --- a/src/coreComponents/mesh/ExternalDataSourceManager.cpp +++ b/src/coreComponents/mesh/ExternalDataSourceManager.cpp @@ -36,7 +36,8 @@ ExternalDataSourceManager::~ExternalDataSourceManager() Group * ExternalDataSourceManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< ExternalDataSourceBase > externalDataSource = ExternalDataSourceBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< ExternalDataSourceBase > externalDataSource = + ExternalDataSourceBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< ExternalDataSourceBase >( childName, std::move( externalDataSource ) ); } diff --git a/src/coreComponents/mesh/MeshManager.cpp b/src/coreComponents/mesh/MeshManager.cpp index 662b06002b..36fdfb0bbf 100644 --- a/src/coreComponents/mesh/MeshManager.cpp +++ b/src/coreComponents/mesh/MeshManager.cpp @@ -43,7 +43,8 @@ MeshManager::~MeshManager() Group * MeshManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< MeshGeneratorBase > mesh = MeshGeneratorBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< MeshGeneratorBase > mesh = + MeshGeneratorBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< MeshGeneratorBase >( childName, std::move( mesh ) ); } diff --git a/src/coreComponents/mesh/ParticleManager.cpp b/src/coreComponents/mesh/ParticleManager.cpp index 314c23120b..057533e4f7 100644 --- a/src/coreComponents/mesh/ParticleManager.cpp +++ b/src/coreComponents/mesh/ParticleManager.cpp @@ -86,14 +86,11 @@ void ParticleManager::setMaxGlobalIndex() Group * ParticleManager::createChild( string const & childKey, string const & childName ) { - GEOS_ERROR_IF( !(CatalogInterface::hasKeyName( childKey )), - "KeyName ("<getGroup( ParticleManager::groupKeyStruct::particleRegionsGroup() ); return &particleRegions.registerGroup( childName, - CatalogInterface::factory( childKey, childName, &particleRegions ) ); - + CatalogInterface::factory( childKey, getDataContext(), + childName, &particleRegions ) ); } void ParticleManager::expandObjectCatalogs() diff --git a/src/coreComponents/mesh/generators/CellBlockManager.cpp b/src/coreComponents/mesh/generators/CellBlockManager.cpp index 2dd41c0987..8ecabcba9e 100644 --- a/src/coreComponents/mesh/generators/CellBlockManager.cpp +++ b/src/coreComponents/mesh/generators/CellBlockManager.cpp @@ -46,6 +46,7 @@ void CellBlockManager::resize( integer_array const & numElements, Group * CellBlockManager::createChild( string const & GEOS_UNUSED_PARAM( childKey ), string const & GEOS_UNUSED_PARAM( childName ) ) { + // Unused as all children are created within the constructor return nullptr; } diff --git a/src/coreComponents/mesh/generators/MeshGeneratorBase.cpp b/src/coreComponents/mesh/generators/MeshGeneratorBase.cpp index 555bef9216..86eb7f0b84 100644 --- a/src/coreComponents/mesh/generators/MeshGeneratorBase.cpp +++ b/src/coreComponents/mesh/generators/MeshGeneratorBase.cpp @@ -30,8 +30,9 @@ MeshGeneratorBase::MeshGeneratorBase( string const & name, Group * const parent Group * MeshGeneratorBase::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< MeshComponentBase > comp = MeshComponentBase::CatalogInterface::factory( childKey, childName, this ); - return &this->registerGroup< MeshComponentBase >( childName, std::move( comp ) ); + std::unique_ptr< MeshComponentBase > meshComp = + MeshComponentBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); + return &this->registerGroup< MeshComponentBase >( childName, std::move( meshComp ) ); } void MeshGeneratorBase::expandObjectCatalogs() diff --git a/src/coreComponents/mesh/generators/ParticleBlockManager.cpp b/src/coreComponents/mesh/generators/ParticleBlockManager.cpp index d96f11711d..f219072ab8 100644 --- a/src/coreComponents/mesh/generators/ParticleBlockManager.cpp +++ b/src/coreComponents/mesh/generators/ParticleBlockManager.cpp @@ -38,6 +38,7 @@ void ParticleBlockManager::resize( integer_array const & numParticles, Group * ParticleBlockManager::createChild( string const & GEOS_UNUSED_PARAM( childKey ), string const & GEOS_UNUSED_PARAM( childName ) ) { + // Unused as all children are created within the constructor return nullptr; } diff --git a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp index f64e0e9b7d..af80ec09c8 100644 --- a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp +++ b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp @@ -74,20 +74,15 @@ WellGeneratorBase::WellGeneratorBase( string const & name, Group * const parent Group * WellGeneratorBase::createChild( string const & childKey, string const & childName ) { - if( childKey == viewKeyStruct::perforationString() ) - { - ++m_numPerforations; + GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); + const auto childTypes = { viewKeyStruct::perforationString() }; + GEOS_ERROR_IF( childKey != viewKeyStruct::perforationString(), + CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); - // keep track of the perforations that have been added - m_perforationList.emplace_back( childName ); - GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - return ®isterGroup< Perforation >( childName ); - } - else - { - GEOS_THROW( "Unrecognized node: " << childKey, InputError ); - } - return nullptr; + ++m_numPerforations; + m_perforationList.emplace_back( childName ); + + return ®isterGroup< Perforation >( childName ); } void WellGeneratorBase::expandObjectCatalogs() diff --git a/src/coreComponents/mesh/simpleGeometricObjects/GeometricObjectManager.cpp b/src/coreComponents/mesh/simpleGeometricObjects/GeometricObjectManager.cpp index c5843dbc74..4209636f4d 100644 --- a/src/coreComponents/mesh/simpleGeometricObjects/GeometricObjectManager.cpp +++ b/src/coreComponents/mesh/simpleGeometricObjects/GeometricObjectManager.cpp @@ -54,7 +54,8 @@ GeometricObjectManager & GeometricObjectManager::getInstance() Group * GeometricObjectManager::createChild( string const & childKey, string const & childName ) { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - std::unique_ptr< SimpleGeometricObjectBase > geometriObject = SimpleGeometricObjectBase::CatalogInterface::factory( childKey, childName, this ); + std::unique_ptr< SimpleGeometricObjectBase > geometriObject = + SimpleGeometricObjectBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); return &this->registerGroup< SimpleGeometricObjectBase >( childName, std::move( geometriObject ) ); } diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 14ec3cbfd4..277bb7b032 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -191,6 +191,7 @@ void PhysicsSolverBase::registerDataOnMesh( Group & meshBodies ) Group * PhysicsSolverBase::createChild( string const & GEOS_UNUSED_PARAM( childKey ), string const & GEOS_UNUSED_PARAM( childName ) ) { + // Unused as all children are created within the constructor return nullptr; } diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverManager.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverManager.cpp index 0267c7df81..9301cf5ee6 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverManager.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverManager.cpp @@ -46,14 +46,10 @@ PhysicsSolverManager::~PhysicsSolverManager() //START_SPHINX_INCLUDE_00 Group * PhysicsSolverManager::createChild( string const & childKey, string const & childName ) { - Group * rval = nullptr; - if( PhysicsSolverBase::CatalogInterface::hasKeyName( childKey ) ) - { - GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); - rval = ®isterGroup( childName, - PhysicsSolverBase::CatalogInterface::factory( childKey, childName, this ) ); - } - return rval; + GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); + std::unique_ptr< PhysicsSolverBase > solver = + PhysicsSolverBase::CatalogInterface::factory( childKey, getDataContext(), childName, this ); + return ®isterGroup< PhysicsSolverBase >( childName, std::move( solver ) ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index e7496035ec..1b7ed01bb4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -67,17 +67,10 @@ WellSolverBase::WellSolverBase( string const & name, Group *WellSolverBase::createChild( string const & childKey, string const & childName ) { - Group *rval = nullptr; - - if( childKey == keys::wellControls ) - { - rval = ®isterGroup< WellControls >( childName ); - } - else - { - PhysicsSolverBase::createChild( childKey, childName ); - } - return rval; + const auto childTypes = { keys::wellControls }; + GEOS_ERROR_IF( childKey != keys::wellControls, + PhysicsSolverBase::CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); + return ®isterGroup< WellControls >( childName ); } void WellSolverBase::expandObjectCatalogs() diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index e130b1e56d..27cb9f836a 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3245,7 +3245,7 @@ Level 0 outputs no specific information for this solver. Higher levels require m - + @@ -3268,7 +3268,7 @@ Local- Add jump stabilization on interior of macro elements--> - + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 3abf5b863f..64384a62a0 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -486,7 +486,7 @@ - + @@ -572,7 +572,7 @@ - + @@ -609,7 +609,7 @@ - + @@ -660,7 +660,7 @@ - + @@ -701,7 +701,7 @@ - + @@ -734,7 +734,7 @@ - + @@ -745,7 +745,7 @@ - + @@ -758,7 +758,7 @@ - + @@ -771,7 +771,7 @@ - + @@ -787,7 +787,7 @@ - + @@ -821,7 +821,7 @@ - + @@ -884,7 +884,7 @@ - + @@ -915,7 +915,7 @@ - + @@ -928,7 +928,7 @@ - + @@ -941,7 +941,7 @@ - + @@ -954,7 +954,7 @@ - + @@ -967,7 +967,7 @@ - + @@ -982,7 +982,7 @@ - + @@ -993,7 +993,7 @@ - + @@ -1006,7 +1006,7 @@ - + @@ -1017,7 +1017,7 @@ - + @@ -1028,7 +1028,7 @@ - + @@ -1039,7 +1039,7 @@ - + @@ -1050,7 +1050,7 @@ - + @@ -1063,7 +1063,7 @@ - + @@ -1074,7 +1074,7 @@ - + @@ -1085,7 +1085,7 @@ - + @@ -1098,7 +1098,7 @@ - + @@ -1113,7 +1113,7 @@ - + @@ -1128,7 +1128,7 @@ - + @@ -1141,7 +1141,7 @@ - + @@ -1156,7 +1156,7 @@ - + @@ -1167,7 +1167,7 @@ - + @@ -1180,7 +1180,7 @@ - + @@ -1193,7 +1193,7 @@ - + @@ -1208,7 +1208,7 @@ - + @@ -1224,7 +1224,7 @@ - + @@ -1239,7 +1239,7 @@ - + @@ -1256,7 +1256,7 @@ - + @@ -1273,7 +1273,7 @@ - + @@ -1290,7 +1290,7 @@ - + @@ -1305,7 +1305,7 @@ - + @@ -1318,7 +1318,7 @@ - + @@ -1357,7 +1357,7 @@ - + @@ -1386,7 +1386,7 @@ - + @@ -1479,7 +1479,7 @@ - + @@ -3103,7 +3103,7 @@ - + @@ -3131,7 +3131,7 @@ - + @@ -3150,11 +3150,11 @@ - + - + @@ -3164,7 +3164,7 @@ - + @@ -3174,11 +3174,11 @@ - + - + @@ -3188,7 +3188,7 @@ - + @@ -3198,7 +3198,7 @@ - + @@ -3208,7 +3208,7 @@ - + @@ -3232,7 +3232,7 @@ - + @@ -3250,7 +3250,7 @@ - + @@ -3262,7 +3262,7 @@ - + @@ -3274,7 +3274,7 @@ - + @@ -3282,11 +3282,11 @@ - + - + @@ -3309,7 +3309,7 @@ - + @@ -3335,7 +3335,7 @@ - + @@ -3356,7 +3356,7 @@ - + @@ -3386,7 +3386,7 @@ - + @@ -3400,7 +3400,7 @@ - + @@ -3427,7 +3427,7 @@ - + @@ -3466,7 +3466,7 @@ - + diff --git a/src/coreComponents/unitTests/dataRepositoryTests/testObjectCatalog.cpp b/src/coreComponents/unitTests/dataRepositoryTests/testObjectCatalog.cpp index 586e4fb3bc..737981ea00 100644 --- a/src/coreComponents/unitTests/dataRepositoryTests/testObjectCatalog.cpp +++ b/src/coreComponents/unitTests/dataRepositoryTests/testObjectCatalog.cpp @@ -17,6 +17,7 @@ // Source includes #include "dataRepository/ObjectCatalog.hpp" +#include "dataRepository/DataContext.hpp" #include "common/logger/Logger.hpp" #include "mainInterface/initialization.hpp" @@ -67,7 +68,6 @@ class Derived1 : public Base } static string catalogName() { return "derived1"; } string getCatalogName() { return catalogName(); } - }; REGISTER_CATALOG_ENTRY( Base, Derived1, int &, double const & ) //STOP_SPHINX @@ -99,14 +99,17 @@ TEST( testObjectCatalog, testRegistration ) GEOS_LOG( "EXECUTING MAIN" ); int junk = 1; double junk2 = 3.14; + dataRepository::DataFileContext const context = dataRepository::DataFileContext( "Base Test Class", __FILE__, __LINE__ ); // allocate a new Derived1 object std::unique_ptr< Base > - derived1 = Base::CatalogInterface::factory( "derived1", junk, junk2 ); + derived1 = Base::CatalogInterface::factory( "derived1", context, + junk, junk2 ); // allocate a new Derived2 object std::unique_ptr< Base > - derived2 = Base::CatalogInterface::factory( "derived2", junk, junk2 ); + derived2 = Base::CatalogInterface::factory( "derived2", context, + junk, junk2 ); EXPECT_STREQ( derived1->getCatalogName().c_str(), Derived1::catalogName().c_str() );