diff --git a/framework/DataObjects/TestXHistorySet.py b/framework/DataObjects/TestXHistorySet.py index 4ed2f62d46..e6e9e99999 100644 --- a/framework/DataObjects/TestXHistorySet.py +++ b/framework/DataObjects/TestXHistorySet.py @@ -644,6 +644,44 @@ def formatRealization(rlz): checkRlz('No input space',rlz0,rlz,skip='Timelike') + +###################################### +# ASYNC HISTORIES # +###################################### +xml = createElement('HistorySet',attrib={'name':'test'}) +xml.append(createElement('Input',text='a,b')) +xml.append(createElement('Output',text='x,y')) +data = XHistorySet.HistorySet() +data.messageHandler = mh +data._readMoreXML(xml) +rlz1 = {'a': np.array([1.0]), + 'b': np.array([2.0]), + 'x': np.array([1.0, 2.0, 3.0]), + 'y': np.array([6.0, 7.0, 8.0]), + 'time': np.array([0.0, 0.1, 0.2])} + +rlz2 = {'a': np.array([11.0]), + 'b': np.array([12.0]), + 'x': np.array([11.0, 12.0]), + 'y': np.array([16.0, 17.0]), + 'time': np.array([0.05, 0.15])} + +data.addRealization(rlz1) +data.addRealization(rlz2) +# check collection in realizations, in collector +checkRlz('Adding asynchronous histories, collector[0]',data.realization(index=0),rlz1,skip=['time']) +checkRlz('Adding asynchronous histories, collector[1]',data.realization(index=1),rlz2,skip=['time']) +# check stored in collector, not in synced histories +idx = data._orderedVars.index('time') +times = data._collector[:,idx] +checkArray('Asynchronous histories, collector, time[0]',times[0],rlz1['time'],float) +checkArray('Asynchronous histories, collector, time[1]',times[1],rlz2['time'],float) +# check as dataset, just for kicks +data.asDataset() +checkRlz('Adding asynchronous histories, dataset[0]',data.realization(index=0),rlz1,skip=['time']) +checkRlz('Adding asynchronous histories, dataset[1]',data.realization(index=1),rlz2,skip=['time']) + + print(results) sys.exit(results["fail"]) diff --git a/framework/DataObjects/XDataSet.py b/framework/DataObjects/XDataSet.py index a7c7de4553..370279252c 100644 --- a/framework/DataObjects/XDataSet.py +++ b/framework/DataObjects/XDataSet.py @@ -162,7 +162,7 @@ def addRealization(self,rlz): rlz = self._selectiveRealization(rlz) ## check alignment of indexes - self._checkAlignedIndexes(rlz) # TODO implement + self._checkAlignedIndexes(rlz) # NB If no scalar entry is made, this construction fails. In that case, # instead of treating each dataarrray as an object, numpy.asarray calls their asarray methods, # unfolding them and making a full numpy array with more dimensions, instead of effectively @@ -689,11 +689,17 @@ def _checkAlignedIndexes(self,rlz,tol=1e-15): for index in self.indexes: # if it's aligned so far, check if it still is if index in self._alignedIndexes.keys(): - # if close enough, then keep the aligned values; otherwise, take action - if isinstance(rlz[index][0],(float,int)): - closeEnough = all(np.isclose(rlz[index],self._alignedIndexes[index],rtol=tol)) + # first, if lengths don't match, they're not aligned. + # TODO there are concerns this check may slow down runs; it should be profiled along with other bottlenecks to optimize our efforts. + if len(rlz[index]) != len(self._alignedIndexes[index]): + closeEnough = False else: - closeEnough = all(rlz[index] == self._alignedIndexes[index]) + # "close enough" if float/int, otherwise require exactness + if isinstance(rlz[index][0],(float,int)): + closeEnough = all(np.isclose(rlz[index],self._alignedIndexes[index],rtol=tol)) + else: + closeEnough = all(rlz[index] == self._alignedIndexes[index]) + # if close enough, then keep the aligned values; otherwise, take action if not closeEnough: dtype = rlz[index].dtype # TODO add new column to collector, propagate values up to (not incl) current rlz