Skip to content

Commit 3d18c00

Browse files
Add support for split nodes
1 parent f5a1776 commit 3d18c00

5 files changed

Lines changed: 394 additions & 45 deletions

File tree

.github/workflows/github-actions.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@ jobs:
99
steps:
1010
- uses: actions/checkout@v5
1111
- name: zlib install
12+
shell: pwsh
1213
run: |
14+
# Download and extract
1315
curl -L "https://zlib.net/current/zlib.tar.gz" -o "${{ runner.temp }}\zlib.tar.gz"
1416
cd ${{ runner.temp }}
15-
tar -xzf ${{ runner.temp }}\zlib.tar.gz
17+
tar -xzf zlib.tar.gz
18+
# Detect extracted folder (handles zlib-1.3.1 or future versions)
19+
$zlibSrc = Get-ChildItem -Directory | Where-Object { $_.Name -like "zlib-*" } | Select-Object -First 1
20+
Write-Host ("Detected zlib source folder: " + $zlibSrc.FullName)
21+
# Build directory
1622
mkdir zlib-build
1723
cd zlib-build
24+
# Configure and install
1825
cmake -G"Visual Studio 17 2022" -A x64 -T host=x64 -Wno-dev -Wno-deprecated -DCMAKE_INSTALL_PREFIX=${{ runner.temp }}/zlib-install ${{ runner.temp }}/zlib-1.3.1
1926
cmake --build . --config Release -j2
2027
cmake --build . --config Release --target INSTALL

src/resqml2/AbstractColumnLayerGridRepresentation.cpp

Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void AbstractColumnLayerGridRepresentation::setIntervalAssociationWithStratigrap
102102
rep->IntervalStratigraphicUnits->UnitIndices = gsoap_eml2_3::soap_new_eml23__JaggedArray(rep->soap);
103103
// element XML
104104
gsoap_eml2_3::eml23__IntegerXmlArray* elementDataset = gsoap_eml2_3::soap_new_eml23__IntegerXmlArray(rep->soap);
105-
elementDataset->CountPerValue = nullValue;
105+
elementDataset->NullValue = nullValue;
106106
elementDataset->Values = std::to_string(stratiUnitIndices[0]);
107107
for (uint64_t i = 1; i < getKCellCount(); ++i) {
108108
elementDataset->Values += " " + std::to_string(stratiUnitIndices[i]);
@@ -111,7 +111,7 @@ void AbstractColumnLayerGridRepresentation::setIntervalAssociationWithStratigrap
111111

112112
// cumulative XML
113113
gsoap_eml2_3::eml23__IntegerXmlArray* cumulativeDataset = gsoap_eml2_3::soap_new_eml23__IntegerXmlArray(rep->soap);
114-
cumulativeDataset->CountPerValue = 1;
114+
cumulativeDataset->NullValue = nullValue;
115115
cumulativeDataset->Values = "1";
116116
for (uint64_t i = 1; i < getKCellCount(); ++i) {
117117
cumulativeDataset->Values += " " + std::to_string(i + 1);
@@ -269,3 +269,166 @@ gsoap_resqml2_0_1::resqml20__PillarShape AbstractColumnLayerGridRepresentation::
269269
throw logic_error("Not implemented yet");
270270
}
271271
}
272+
273+
void AbstractColumnLayerGridRepresentation::getSplitNodeParentNodeIndices(uint64_t* splitNodeParentNodeIndices) const
274+
{
275+
if (gsoapProxy2_0_1 != nullptr) {
276+
gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry*>(getPointGeometry2_0_1(0));
277+
if (geom == nullptr) {
278+
throw invalid_argument("There is no geometry on this grid.");
279+
}
280+
if (geom->SplitNodes == nullptr || geom->SplitNodes->Count == 0) {
281+
throw invalid_argument("There is no split node on this grid.");
282+
}
283+
284+
readArrayNdOfIntegerValues(geom->SplitNodes->ParentNodeIndices, splitNodeParentNodeIndices);
285+
}
286+
else {
287+
gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry*>(getPointGeometry2_2(0));
288+
if (geom == nullptr) {
289+
throw invalid_argument("There is no geometry on this grid.");
290+
}
291+
if (geom->SplitNodePatch == nullptr || geom->SplitNodePatch->Count == 0) {
292+
throw invalid_argument("There is no split node on this grid.");
293+
}
294+
295+
readArrayNdOfIntegerValues(geom->SplitNodePatch->ParentNodeIndices, splitNodeParentNodeIndices);
296+
}
297+
}
298+
299+
void AbstractColumnLayerGridRepresentation::getCumulativeCountOfCellsPerSplitNode(uint64_t* cumulativeCountOfCellsPerSplitNode) const
300+
{
301+
if (gsoapProxy2_0_1 != nullptr) {
302+
gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry*>(getPointGeometry2_0_1(0));
303+
if (geom == nullptr) {
304+
throw invalid_argument("There is no geometry on this grid.");
305+
}
306+
if (geom->SplitNodes == nullptr || geom->SplitNodes->Count == 0) {
307+
throw invalid_argument("There is no split node on this grid.");
308+
}
309+
310+
readArrayNdOfIntegerValues(geom->SplitNodes->CellsPerSplitNode->CumulativeLength, cumulativeCountOfCellsPerSplitNode);
311+
}
312+
else {
313+
gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry*>(getPointGeometry2_2(0));
314+
if (geom == nullptr) {
315+
throw invalid_argument("There is no geometry on this grid.");
316+
}
317+
if (geom->SplitNodePatch == nullptr || geom->SplitNodePatch->Count == 0) {
318+
throw invalid_argument("There is no split node on this grid.");
319+
}
320+
321+
readArrayNdOfIntegerValues(geom->SplitNodePatch->CellsPerSplitNode->CumulativeLength, cumulativeCountOfCellsPerSplitNode);
322+
}
323+
}
324+
325+
void AbstractColumnLayerGridRepresentation::getCellsPerSplitNode(uint64_t* cellsPerSplitNode) const
326+
{
327+
if (gsoapProxy2_0_1 != nullptr) {
328+
gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry*>(getPointGeometry2_0_1(0));
329+
if (geom == nullptr) {
330+
throw invalid_argument("There is no geometry on this grid.");
331+
}
332+
if (geom->SplitNodes == nullptr || geom->SplitNodes->Count == 0) {
333+
throw invalid_argument("There is no split node on this grid.");
334+
}
335+
336+
readArrayNdOfIntegerValues(geom->SplitNodes->CellsPerSplitNode->Elements, cellsPerSplitNode);
337+
}
338+
else {
339+
gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry*>(getPointGeometry2_2(0));
340+
if (geom == nullptr) {
341+
throw invalid_argument("There is no geometry on this grid.");
342+
}
343+
if (geom->SplitNodePatch == nullptr || geom->SplitNodePatch->Count == 0) {
344+
throw invalid_argument("There is no split node on this grid.");
345+
}
346+
347+
readArrayNdOfIntegerValues(geom->SplitNodePatch->CellsPerSplitNode->Elements, cellsPerSplitNode);
348+
}
349+
}
350+
351+
void AbstractColumnLayerGridRepresentation::setSplitNodePatch(uint64_t splitNodeCount, uint64_t* splitNodeParentNodeIndices,
352+
uint64_t* cumulativeCountOfCellsPerSplitNode, uint64_t* cellsPerSplitNode, EML2_NS::AbstractHdfProxy* proxy)
353+
{
354+
if (proxy == nullptr) {
355+
proxy = getRepository()->getDefaultHdfProxy();
356+
if (proxy == nullptr) {
357+
throw std::invalid_argument("A (default) HDF Proxy must be provided.");
358+
}
359+
}
360+
361+
if (gsoapProxy2_0_1 != nullptr) {
362+
gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_resqml2_0_1::resqml20__AbstractColumnLayerGridGeometry*>(getPointGeometry2_0_1(0));
363+
if (geom == nullptr) {
364+
throw invalid_argument("There is no geometry on this grid.");
365+
}
366+
367+
auto* patch = soap_new_resqml20__SplitNodePatch(gsoapProxy2_0_1->soap);
368+
patch->Count = splitNodeCount;
369+
370+
auto* parentNodeIndicesArray = soap_new_resqml20__IntegerHdf5Array(gsoapProxy2_0_1->soap);
371+
parentNodeIndicesArray->Values = soap_new_eml20__Hdf5Dataset(gsoapProxy2_0_1->soap);
372+
parentNodeIndicesArray->Values->HdfProxy = proxy->newResqmlReference();
373+
parentNodeIndicesArray->Values->PathInHdfFile = getHdfGroup() + "/SplitNodeParentNodeIndices";
374+
parentNodeIndicesArray->NullValue = -1;
375+
patch->ParentNodeIndices = parentNodeIndicesArray;
376+
377+
patch->CellsPerSplitNode = soap_new_resqml20__ResqmlJaggedArray(gsoapProxy2_0_1->soap);
378+
// Cumulative
379+
resqml20__IntegerHdf5Array* cumulativeLength = soap_new_resqml20__IntegerHdf5Array(gsoapProxy2_0_1->soap);
380+
patch->CellsPerSplitNode->CumulativeLength = cumulativeLength;
381+
cumulativeLength->NullValue = -1;
382+
cumulativeLength->Values = soap_new_eml20__Hdf5Dataset(gsoapProxy2_0_1->soap);
383+
cumulativeLength->Values->HdfProxy = proxy->newResqmlReference();
384+
cumulativeLength->Values->PathInHdfFile = getHdfGroup() + "/CellsPerSplitNode/" + EML2_NS::AbstractHdfProxy::CUMULATIVE_LENGTH_DS_NAME;
385+
// Elements
386+
resqml20__IntegerHdf5Array* elements = soap_new_resqml20__IntegerHdf5Array(gsoapProxy2_0_1->soap);
387+
patch->CellsPerSplitNode->Elements = elements;
388+
elements->NullValue = -1;
389+
elements->Values = soap_new_eml20__Hdf5Dataset(gsoapProxy2_0_1->soap);
390+
elements->Values->HdfProxy = proxy->newResqmlReference();
391+
elements->Values->PathInHdfFile = getHdfGroup() + "/CellsPerSplitNode/" + EML2_NS::AbstractHdfProxy::ELEMENTS_DS_NAME;
392+
393+
geom->SplitNodes = patch;
394+
}
395+
else {
396+
gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry* geom = dynamic_cast<gsoap_eml2_3::resqml22__AbstractColumnLayerGridGeometry*>(getPointGeometry2_2(0));
397+
if (geom == nullptr) {
398+
throw invalid_argument("There is no geometry on this grid.");
399+
}
400+
401+
auto* patch = gsoap_eml2_3::soap_new_resqml22__SplitNodePatch(gsoapProxy2_3->soap);
402+
patch->Count = splitNodeCount;
403+
404+
auto* parentNodeIndicesArray = gsoap_eml2_3::soap_new_eml23__IntegerExternalArray(gsoapProxy2_3->soap);
405+
parentNodeIndicesArray->Values = gsoap_eml2_3::soap_new_eml23__ExternalDataArray(gsoapProxy2_3->soap);
406+
parentNodeIndicesArray->Values->ExternalDataArrayPart.push_back(createExternalDataArrayPart(getHdfGroup() + "/SplitNodeParentNodeIndices", splitNodeCount, proxy));
407+
parentNodeIndicesArray->NullValue = -1;
408+
patch->ParentNodeIndices = parentNodeIndicesArray;
409+
410+
patch->CellsPerSplitNode = gsoap_eml2_3::soap_new_eml23__JaggedArray(gsoapProxy2_3->soap);
411+
// cumulative XML
412+
auto* cumulativeDataset = gsoap_eml2_3::soap_new_eml23__IntegerExternalArray(gsoapProxy2_3->soap);
413+
cumulativeDataset->NullValue = -1;
414+
cumulativeDataset->Values = gsoap_eml2_3::soap_new_eml23__ExternalDataArray(gsoapProxy2_3->soap);
415+
cumulativeDataset->Values->ExternalDataArrayPart.push_back(
416+
createExternalDataArrayPart(getHdfGroup() + "/CellsPerSplitNode/" + EML2_NS::AbstractHdfProxy::CUMULATIVE_LENGTH_DS_NAME, splitNodeCount, proxy));
417+
patch->CellsPerSplitNode->CumulativeLength = cumulativeDataset;
418+
// element XML
419+
auto* elementDataset = gsoap_eml2_3::soap_new_eml23__IntegerExternalArray(gsoapProxy2_3->soap);
420+
elementDataset->NullValue = -1;
421+
elementDataset->Values = gsoap_eml2_3::soap_new_eml23__ExternalDataArray(gsoapProxy2_3->soap);
422+
elementDataset->Values->ExternalDataArrayPart.push_back(
423+
createExternalDataArrayPart(getHdfGroup() + "/CellsPerSplitNode/" + EML2_NS::AbstractHdfProxy::ELEMENTS_DS_NAME, cumulativeCountOfCellsPerSplitNode[splitNodeCount-1], proxy));
424+
patch->CellsPerSplitNode->Elements = elementDataset;
425+
426+
geom->SplitNodePatch = patch;
427+
}
428+
429+
// HDF
430+
proxy->writeArrayNdOfUInt64Values(getHdfGroup(), "SplitNodeParentNodeIndices", splitNodeParentNodeIndices, &splitNodeCount, 1);
431+
proxy->writeItemizedListOfList(getHdfGroup(), "CellsPerSplitNode",
432+
COMMON_NS::AbstractObject::numericalDatatypeEnum::UINT64, cumulativeCountOfCellsPerSplitNode, splitNodeCount,
433+
COMMON_NS::AbstractObject::numericalDatatypeEnum::UINT64, cellsPerSplitNode, cumulativeCountOfCellsPerSplitNode[splitNodeCount - 1]);
434+
}

src/resqml2/AbstractColumnLayerGridRepresentation.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,65 @@ namespace RESQML2_NS
126126
*/
127127
DLL_IMPORT_OR_EXPORT gsoap_resqml2_0_1::resqml20__PillarShape getMostComplexPillarGeometry() const;
128128

129+
/**
130+
* Gets the parent node index for each of the split nodes.
131+
*
132+
* @param [out] splitNodeParentNodeIndices This array must be pre-allocated with a size equal to the
133+
* count of split nodes. It will be filled in by this method
134+
* and not deleted.
135+
*
136+
* @exception std::invalid_argument If there is no split node on this column layer grid.
137+
*/
138+
DLL_IMPORT_OR_EXPORT void getSplitNodeParentNodeIndices(uint64_t* splitNodeParentNodeIndices) const;
139+
140+
/**
141+
* Gets the cumulative count of cells impacted by all the split nodes. The order of
142+
* the cumulative count values corresponds to the order of the split nodes.
143+
*
144+
* @exception std::invalid_argument If the HDF proxy is missing.
145+
* @exception std::invalid_argument If there is no geometry or no split node in
146+
* this grid.
147+
* @exception std::logic_error If the cumulative count of the columns impacted by the
148+
* split coordinate lines are not stored within an HDF5
149+
* integer array.
150+
*
151+
* @param [out] cumulativeCountOfCellsPerSplitNode This array must be pre-allocated with a size equal to the
152+
* count of split nodes. It will be filled in with the cumulative
153+
* count of cells impacted by the split nodes.
154+
*/
155+
DLL_IMPORT_OR_EXPORT void getCumulativeCountOfCellsPerSplitNode(uint64_t* cumulativeCountOfCellsPerSplitNode) const;
156+
157+
/**
158+
* Gets the indices of the cells impacted by all the split nodes. They are linearized and must be read according to getCumulativeCountOfCellsPerSplitNode.
159+
*
160+
* @exception std::invalid_argument If the HDF proxy is missing.
161+
* @exception std::invalid_argument If there is no geometry or no split node in
162+
* this grid.
163+
* @exception std::logic_error If the cumulative count of the columns impacted by the
164+
* split coordinate lines are not stored within an HDF5
165+
* integer array.
166+
*
167+
* @param [out] cellsPerSplitNode This array must be pre-allocated with the last value of the
168+
* getCumulativeCountOfCellsPerSplitNode returned value.
169+
* It will be filled in with the cell indices impacted by the split nodes.
170+
*/
171+
DLL_IMPORT_OR_EXPORT void getCellsPerSplitNode(uint64_t* cellsPerSplitNode) const;
172+
173+
/**
174+
* Sets all information about a split node patch of the grid. These information is related to
175+
* all XYZ points which are located after the index (PillarCount + SplitPillarCount + SplitCoordinateLineCount) * (KCellCount + 1)
176+
*
177+
* @param [in] splitNodeCount The count of split nodes
178+
* @param [in] splitNodeParentNodeIndices The parent node index for each of the split nodes. Size must be splitNodeCount.
179+
* @param [in] cumulativeCountOfCellsPerSplitNode The cumulative count of cells impacted by each of the split nodes. Size must be splitNodeCount.
180+
* @param [in] cellsPerSplitNode The indices of the cells impacted by each of the split nodes.
181+
* Size must be the last value of cumulativeCountOfCellsPerSplitNode
182+
* @param [in]proxy (Optional) The HDF proxy for writing the array values.
183+
* If @c nullptr (default), then the default HDF proxy will be used.
184+
*/
185+
DLL_IMPORT_OR_EXPORT void setSplitNodePatch(uint64_t splitNodeCount, uint64_t* splitNodeParentNodeIndices,
186+
uint64_t* cumulativeCountOfCellsPerSplitNode, uint64_t* cellsPerSplitNode, EML2_NS::AbstractHdfProxy* proxy = nullptr);
187+
129188
protected:
130189

131190
/**

0 commit comments

Comments
 (0)