Skip to content

Conversation

@rrsettgast
Copy link
Member

@rrsettgast rrsettgast commented Mar 26, 2025

MappedVector::insert incorrectly delete object if it is a duplicate entry and the overwrite flag isn't true. This means that the insert is a no-op, and the object that was supposed to be inserted was deleted. Bad news bears.

  • fix incorrect deletion of objects referred to by input pointer
  • removed and disallowed redundant registrations, but provided a registration option to permit existence.
  • removed the redundant name parameter from certain registerGroup and registerWrapper methods.

Related to: GEOS-DEV/LvArray#350

@rrsettgast
Copy link
Member Author

@wrtobin I made the redundant registration attempts an error if the registration doesn't have the same exact pointer address as the existing entry. This is the only case that is OK imo. There are a lot of errors. Things seem to be registered in the mesh generation/ mesh level creation in a quite inconsistent way. No big surprise. Can you have a go at resolving some the errors?

@wrtobin wrtobin requested a review from Copilot April 10, 2025 17:27
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.

Files not reviewed (2)
  • src/coreComponents/schema/schema.xsd: Language not supported
  • src/coreComponents/schema/schema.xsd.other: Language not supported
Comments suppressed due to low confidence (1)

src/coreComponents/dataRepository/MappedVector.hpp:510

  • If 'takeOwnership' is true but the source pointer differs from the existing value, the code only updates the ownership flag without replacing the pointer. Verify that this logic aligns with the intended behavior to correctly handle duplicate entries.
    else if( m_values[index].second != source ) // this insertion is OK if the source pointer is the same address as the existing value

arrayView1d< bool const > const nodeInCurSet = nodeInSet[setName];

SortedArray< localIndex > & targetSet = elementSets.registerWrapper< SortedArray< localIndex > >( setName ).reference();
// SortedArray< localIndex > & targetSet = elementSets.registerWrapper< SortedArray< localIndex > >( setName ).reference();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// SortedArray< localIndex > & targetSet = elementSets.registerWrapper< SortedArray< localIndex > >( setName ).reference();

MeshBody & meshBody = domain.getMeshBodies().registerGroup< MeshBody >( meshGen.getName() );
meshBody.createMeshLevel( 0 );
MeshBody & meshBody = domain.getMeshBodies().getGroup< MeshBody >( meshGen.getName() );
// meshBody.createMeshLevel( 0 );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

setPlotLevel( PlotLevel::NOPLOT );

m_sets.registerWrapper< SortedArray< localIndex > >( this->m_ObjectManagerBaseViewKeys.externalSet );
// m_sets.registerWrapper< SortedArray< localIndex > >( this->m_ObjectManagerBaseViewKeys.externalSet );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// m_sets.registerWrapper< SortedArray< localIndex > >( this->m_ObjectManagerBaseViewKeys.externalSet );

}

// if value is empty, then move source into value slot
if( m_values[index].second==nullptr )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, when do we use this functionality of inserting a nullptr? It seems like the kind of thing that could reasonably be disallowed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

....err....good point.

@paveltomin
Copy link
Collaborator

@rrsettgast is this still active PR?

@rrsettgast
Copy link
Member Author

@wrtobin you were supposed to pick this up a while back.

@corbett5
Copy link
Contributor

I'm gonna try and get this working this week.

@corbett5 corbett5 requested a review from Guotong-Ren as a code owner November 1, 2025 06:54
@corbett5 corbett5 force-pushed the bugfix/invalidDeleteInMappedVector branch from 652a70d to 653ee13 Compare November 2, 2025 06:34
<!-- SPHINX_SOLVER_END -->
</Solvers>

<NumericalMethods>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already present in the included base file.

xMax="{ 101.01, 101.01, 101.01 }"/>
</Geometry>

<!-- The free surface condition the domain -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already present in the included base file.

{
string const wrapperName = makeFieldName( this->getName(), wrapper.first );
parent.registerWrapper( wrapper.second->clone( wrapperName, parent ) ).
parent.registerWrapper( wrapper.second->clone( wrapperName, parent ), true ).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These sorts of changes registerWrapper(..., true) and registerGroup(..., true) permit an object with the given name to already exist, and return the existing object.

Comment on lines +44 to +46
Group * ConstitutiveManager::createChild( string const & childKey,
string const & childName,
bool const allowExistence )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were some places where createChild needed to change, since this is a virtual function in Group, changing the signature there required changes everywhere.

std::unique_ptr< ConstitutiveBase > material =
ConstitutiveBase::CatalogInterface::factory( childKey, getDataContext(), childName, this );
return &registerGroup< ConstitutiveBase >( childName, std::move( material ) );
return &registerGroup< ConstitutiveBase >( std::move( material ), allowExistence );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also made it so that methods such as these, which register an existing Group or Wrapper no longer require an additional name (childName in this example). In every instance in the code the provided name is the same as the name of the Group (or Wrapper itself, and it seems this is something we should enforce.

Comment on lines +92 to +94
auto & set = m_sets.registerWrapper< SortedArray< localIndex > >( newSetName, true ).reference();
set.clear();
return set;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this set.clear() behavior is new.

m_registeredField.insert( FIELD_TRAIT::key());

return this->registerWrapper< typename FIELD_TRAIT::type >( FIELD_TRAIT::key() ).
return this->registerWrapper< typename FIELD_TRAIT::type >( FIELD_TRAIT::key(), nullptr, true ).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nullptr here is to satisfy the following signature without having to introduce a similar function without rkey

template< typename T, typename TBASE=T >
Wrapper< TBASE > & registerWrapper( string const & name,
                                    wrapperMap::KeyIndex::index_type * const rkey = nullptr,
                                    bool const allowExistence=false );

parent )
{
registerWrapper( viewKeyStruct::sourceConstantsString(), &m_sourceConstantsx ).
registerWrapper( viewKeyStruct::sourceConstantsXString(), &m_sourceConstantsx ).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the true mistakes I found. The few failing integrated tests are due to this and will require a rebaseline.

Comment on lines -210 to -213
subRegion.registerWrapper< string >( viewKeyStruct::porousMaterialNamesString() ).
setPlotLevel( dataRepository::PlotLevel::NOPLOT ).
setRestartFlags( dataRepository::RestartFlags::NO_WRITE ).
setSizedFromParent( 0 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These must have been registered elsewhere, but I couldn't find where.

SortedArrayView< localIndex const > const & faceSet = faceManager->sets().getReference< SortedArray< localIndex > >( setIter.first );
SortedArray< localIndex > & faceElementSet = subRegion.sets().registerWrapper< SortedArray< localIndex > >( setIter.first ).reference();
SortedArray< localIndex > & faceElementSet = subRegion.sets().getReference< SortedArray< localIndex > >( setIter.first );
// faceElementSet.clear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rrsettgast For all the set building I initially cleared the set because I mistakenly assumed the old behavior of registerWrapper would replace the previously held data (effectively calling clear). This worked fine everywhere else, in fact I still kept that behavior. But here this presented a problem with some integrated tests having diffs in the the size of FractureElementSubregion/sets/externalSet, but only in parallel.

My question is: do we actually want to clear the sets every time?

@corbett5 corbett5 added ci: run CUDA builds Allows to triggers (costly) CUDA jobs flag: ready for review flag: requires rebaseline Requires rebaseline branch in integratedTests type: bug Something isn't working type: cleanup / refactor Non-functional change (NFC) labels Nov 4, 2025
@corbett5
Copy link
Contributor

corbett5 commented Nov 6, 2025

I updated the error messages and conditions as requested. Here are two examples

***** ERROR
***** LOCATION: /usr/WS2/corbett5/GEOS/develop/src/coreComponents/dataRepository/Group.cpp:774
***** Controlling expression (should be false): true
***** Rank 0: Tried registering a wrapper "pressure_n" of type real64_array with "/domain/MeshBodies/mesh/meshLevels/Level0/nodeManager"
A wrapper of this name already exists with type real32_array. The existing wrapper was registered by the following:
        acousticSolver

***** ERROR
***** LOCATION: /usr/WS2/corbett5/GEOS/develop/src/coreComponents/dataRepository/Group.cpp:801
***** Controlling expression (should be false): !allowExistence || (existingTypeId != typeId)
***** Rank 0: Tried registering a Group "acousticSolver" of type geos::AcousticWaveEquationSEM with "/Solvers"
A Group of this name already exists with type geos::dataRepository::Group

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: ready for review flag: requires rebaseline Requires rebaseline branch in integratedTests flag: requires updated submodule(s) type: bug Something isn't working type: cleanup / refactor Non-functional change (NFC)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants