Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion dynadjust/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ else()
endif()
message(STATUS "Found XercesC (${XercesC_INCLUDE_DIRS} ${XercesC_LIBRARIES})")

# Static builds need ICU for Xerces transcoding (glibc iconv can't dlopen gconv modules in static binaries)
# Static builds need ICU for Xerces transcoding (glibc iconv can't dlopen gconv modules in static binaries).
if(BUILD_STATIC AND UNIX AND NOT APPLE)
find_package(ICU COMPONENTS uc data)
if(ICU_FOUND)
Expand Down Expand Up @@ -1132,6 +1132,53 @@ if (BUILD_TESTING)
add_test (NAME test-urban-phased-network COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> urban.phased.adj urban.phased.adj.expected --skip-to-marker "M Station 1" -t 0.001)
add_test (NAME test-urban-thread-network COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> urban_mt.phased-mt.adj urban_mt.phased-mt.adj.expected --skip-to-marker "M Station 1" -t 0.01 -v)

# ........................................................................
# LM / Trust-Region solver tests
# ........................................................................

# LM-1. GNSS simultaneous with LM — should match GN results
add_test (NAME import-gnss-lm COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n gnss_lm gnss-network.stn gnss-network.msr -r GDA2020 --flag-unused-stations --quiet)
add_test (NAME geoid-gnss-lm COMMAND $<TARGET_FILE:${DNAGEOID_TARGET}> gnss_lm -g gnss-network-geoid.gsb --export-dna-geo)
add_test (NAME reftran-gnss-lm COMMAND $<TARGET_FILE:${DNAREFTRAN_TARGET}> gnss_lm --export-dna --export-xml)
add_test (NAME adjust-gnss-lm COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> gnss_lm --output-adj-msr --scale-normals-to-unity --lm-enabled)
add_test (NAME test-gnss-lm-vs-expected COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> gnss_lm.simult.adj gnss.simult.adj.expected --skip-headers 52 -t 0.001)

# LM-2. Urban phased with LM — should match GN results
add_test (NAME import-urban-lm COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n urban_lm urban-network.stn urban-network.msr --flag-unused-stations --quiet)
add_test (NAME geoid-urban-lm COMMAND $<TARGET_FILE:${DNAGEOID_TARGET}> urban_lm -g urban-network-geoid.gsb --export-dna-geo)
add_test (NAME segment-urban-lm COMMAND $<TARGET_FILE:${DNASEGMENT_TARGET}> urban_lm --min 50 --max 150)
add_test (NAME adjust-urban-lm COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> urban_lm --output-adj-msr --phased --lm-enabled)
add_test (NAME test-urban-lm-vs-expected COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> urban_lm.phased.adj urban.phased.adj.expected --skip-to-marker "M Station 1" -t 0.001)

# LM-3. Urban multi-threaded phased with LM — should match GN results
add_test (NAME import-urban-mt-lm COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n urban_mt_lm urban-network.stn urban-network.msr --quiet)
add_test (NAME reftran-urban-mt-lm COMMAND $<TARGET_FILE:${DNAREFTRAN_TARGET}> urban_mt_lm -r gda2020)
add_test (NAME geoid-urban-mt-lm COMMAND $<TARGET_FILE:${DNAGEOID_TARGET}> urban_mt_lm -g urban-network-geoid.gsb)
add_test (NAME segment-urban-mt-lm COMMAND $<TARGET_FILE:${DNASEGMENT_TARGET}> urban_mt_lm --min 50 --max 85)
add_test (NAME adjust-urban-mt-lm COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> urban_mt_lm --output-adj-msr --multi --lm-enabled)
add_test (NAME test-urban-mt-lm-vs-expected COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> urban_mt_lm.phased-mt.adj urban_mt.phased-mt.adj.expected --skip-to-marker "M Station 1" -t 0.01)

# LM-4. DSG distance-only simultaneous — multi-iteration stress test
add_test (NAME import-dsg-lm COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n dsg_lm dsg.stn dsg.msr --flag-unused-stations --quiet)
add_test (NAME adjust-dsg-lm COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> dsg_lm --output-adj-msr --max-iterations 50 --lm-enabled)

# LM-5. DSG distance-only simultaneous — GN baseline for comparison
add_test (NAME import-dsg-gn COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n dsg_gn dsg.stn dsg.msr --flag-unused-stations --quiet)
add_test (NAME adjust-dsg-gn COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> dsg_gn --output-adj-msr --max-iterations 50)
add_test (NAME test-dsg-lm-vs-gn COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> dsg_lm.simult.adj dsg_gn.simult.adj --skip-headers 52 -t 0.01)

# LM-6. DSG distance-only phased with LM
add_test (NAME import-dsg-ph-lm COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n dsg_ph_lm dsg.stn dsg.msr --flag-unused-stations --quiet)
add_test (NAME segment-dsg-ph-lm COMMAND $<TARGET_FILE:${DNASEGMENT_TARGET}> dsg_ph_lm --min 10 --max 30)
add_test (NAME adjust-dsg-ph-lm COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> dsg_ph_lm --output-adj-msr --phased --max-iterations 50 --lm-enabled)

# LM-7. GNSS simultaneous with large initial lambda (robustness check)
add_test (NAME import-gnss-lm-large-lambda COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n gnss_lm_ll gnss-network.stn gnss-network.msr -r GDA2020 --flag-unused-stations --quiet)
add_test (NAME geoid-gnss-lm-large-lambda COMMAND $<TARGET_FILE:${DNAGEOID_TARGET}> gnss_lm_ll -g gnss-network-geoid.gsb --export-dna-geo)
add_test (NAME reftran-gnss-lm-large-lambda COMMAND $<TARGET_FILE:${DNAREFTRAN_TARGET}> gnss_lm_ll --export-dna --export-xml)
add_test (NAME adjust-gnss-lm-large-lambda COMMAND $<TARGET_FILE:${DNAADJUST_TARGET}> gnss_lm_ll --output-adj-msr --scale-normals-to-unity --lm-enabled --lm-lambda-init 10.0)
add_test (NAME test-gnss-lm-large-lambda COMMAND $<TARGET_FILE:${DNADIFF_TARGET}> gnss_lm_ll.simult.adj gnss.simult.adj.expected --skip-headers 52 -t 0.001)

# 8. Source tag preservation in --export-xml (issue #317)
# Import XML data with <Source> tags and verify they are preserved in export
add_test (NAME import-source-test COMMAND $<TARGET_FILE:${DNAIMPORT_TARGET}> -n srctest source-test-stn.xml source-test-msr.xml --export-xml -r GDA2020)
Expand Down Expand Up @@ -1998,6 +2045,13 @@ if (BUILD_TESTING)
set_tests_properties(test-urban-phased-network PROPERTIES DEPENDS adjust-urban-network)
set_tests_properties(test-urban-thread-network PROPERTIES DEPENDS adjust-urban-network-thread-01)

# LM test dependencies
set_tests_properties(test-gnss-lm-vs-expected PROPERTIES DEPENDS adjust-gnss-lm)
set_tests_properties(test-urban-lm-vs-expected PROPERTIES DEPENDS adjust-urban-lm)
set_tests_properties(test-urban-mt-lm-vs-expected PROPERTIES DEPENDS adjust-urban-mt-lm)
set_tests_properties(test-dsg-lm-vs-gn PROPERTIES DEPENDS "adjust-dsg-lm;adjust-dsg-gn")
set_tests_properties(test-gnss-lm-large-lambda PROPERTIES DEPENDS adjust-gnss-lm-large-lambda)

set_tests_properties(ref-itrf-pmm-06 PROPERTIES DEPENDS ref-itrf-pmm-05)
#set_tests_properties(ref-itrf-pmm-07 PROPERTIES DEPENDS ref-itrf-pmm-06)

Expand Down
13 changes: 11 additions & 2 deletions dynadjust/dynadjust/dnaadjust/dnaadjust-multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ bool prepareAdjustmentExceptionThrown(const std::vector<std::exception_ptr>& pre
//
void dna_adjust::AdjustPhasedMultiThread()
{
if (projectSettings_.a.lm_enabled)
{
AdjustPhasedMultiThreadLM();
return;
}

initialiseIteration();

std::string corr_msg;
Expand Down Expand Up @@ -295,7 +301,7 @@ void dna_adjust::SolveMT(bool COMPUTE_INVERSE, const UINT32& block)
{
// Compute inverse of normals (aposteriori variance matrix)
// (AT * V-1 * A)-1
FormInverseVarianceMatrix(&(v_normalsR_.at(block)), false);
FormInverseVarianceMatrix(&(v_normalsR_.at(block)), false, true);
}

// compute weighted "measured minus computed"
Expand All @@ -304,7 +310,10 @@ void dna_adjust::SolveMT(bool COMPUTE_INVERSE, const UINT32& block)

// Solve corrections from normal equations
v_correctionsR_.at(block).redim(v_designR_.at(block).columns(), 1);
v_correctionsR_.at(block).multiply(v_normalsR_.at(block), "N", At_Vinv_m, "N");
if (v_normalsR_.at(block).is_symmetric())
v_correctionsR_.at(block).multiply_sym(v_normalsR_.at(block), At_Vinv_m);
else
v_correctionsR_.at(block).multiply(v_normalsR_.at(block), "N", At_Vinv_m, "N");

// debug output?
if (projectSettings_.g.verbose > 3)
Expand Down
118 changes: 79 additions & 39 deletions dynadjust/dynadjust/dnaadjust/dnaadjust-stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ void dna_adjust::DeserialiseBlockFromMappedFile(const UINT32& block, const int f
break;
case sf_normals_r:
addr = normalsR_map_.GetBlockRegionAddr(block);
v_normalsR_.at(block).ReadMappedFileRegion(addr);
v_normalsR_.at(block).AttachMappedFileRegion(addr);
break;
case sf_atvinv:
v_AtVinv_.at(block).allocate();
Expand All @@ -183,47 +183,47 @@ void dna_adjust::DeserialiseBlockFromMappedFile(const UINT32& block, const int f
break;
case sf_meas_minus_comp:
addr = measMinusComp_map_.GetBlockRegionAddr(block);
v_measMinusComp_.at(block).ReadMappedFileRegion(addr);
v_measMinusComp_.at(block).AttachMappedFileRegion(addr);
break;
case sf_estimated_stns:
addr = estimatedStations_map_.GetBlockRegionAddr(block);
v_estimatedStations_.at(block).ReadMappedFileRegion(addr);
v_estimatedStations_.at(block).AttachMappedFileRegion(addr);
break;
case sf_original_stns:
addr = originalStations_map_.GetBlockRegionAddr(block);
v_originalStations_.at(block).ReadMappedFileRegion(addr);
v_originalStations_.at(block).AttachMappedFileRegion(addr);
break;
case sf_rigorous_stns:
addr = rigorousStations_map_.GetBlockRegionAddr(block);
v_rigorousStations_.at(block).ReadMappedFileRegion(addr);
v_rigorousStations_.at(block).AttachMappedFileRegion(addr);
break;
case sf_junction_vars:
addr = junctionVariances_map_.GetBlockRegionAddr(block);
v_junctionVariances_.at(block).ReadMappedFileRegion(addr);
v_junctionVariances_.at(block).AttachMappedFileRegion(addr);
break;
case sf_junction_vars_f:
addr = junctionVariancesFwd_map_.GetBlockRegionAddr(block);
v_junctionVariancesFwd_.at(block).ReadMappedFileRegion(addr);
v_junctionVariancesFwd_.at(block).AttachMappedFileRegion(addr);
break;
case sf_junction_ests_f:
addr = junctionEstimatesFwd_map_.GetBlockRegionAddr(block);
v_junctionEstimatesFwd_.at(block).ReadMappedFileRegion(addr);
v_junctionEstimatesFwd_.at(block).AttachMappedFileRegion(addr);
break;
case sf_junction_ests_r:
addr = junctionEstimatesRev_map_.GetBlockRegionAddr(block);
v_junctionEstimatesRev_.at(block).ReadMappedFileRegion(addr);
v_junctionEstimatesRev_.at(block).AttachMappedFileRegion(addr);
break;
case sf_rigorous_vars:
addr = rigorousVariances_map_.GetBlockRegionAddr(block);
v_rigorousVariances_.at(block).ReadMappedFileRegion(addr);
v_rigorousVariances_.at(block).AttachMappedFileRegion(addr);
break;
case sf_prec_adj_msrs:
addr = precAdjMsrs_map_.GetBlockRegionAddr(block);
v_precAdjMsrsFull_.at(block).ReadMappedFileRegion(addr);
v_precAdjMsrsFull_.at(block).AttachMappedFileRegion(addr);
break;
case sf_corrections:
addr = corrections_map_.GetBlockRegionAddr(block);
v_corrections_.at(block).ReadMappedFileRegion(addr);
v_corrections_.at(block).AttachMappedFileRegion(addr);

if (v_blockMeta_.at(block)._blockLast)
v_correctionsR_.at(block).allocate();
Expand All @@ -240,8 +240,8 @@ void dna_adjust::SerialiseBlockToMappedFile(const UINT32& block, const int file_
{
// serialise all. That is, call this function again, but with
// arguments for all files
SerialiseBlockToMappedFile(block, 16,
sf_normals, sf_normals_r, sf_atvinv, sf_design, sf_meas_minus_comp,
SerialiseBlockToMappedFile(block, 12,
sf_normals_r, sf_meas_minus_comp,
sf_estimated_stns, sf_original_stns, sf_rigorous_stns,
sf_junction_vars, sf_junction_vars_f, sf_junction_ests_f, sf_junction_ests_r,
sf_rigorous_vars, sf_prec_adj_msrs, sf_corrections);
Expand All @@ -257,16 +257,10 @@ void dna_adjust::SerialiseBlockToMappedFile(const UINT32& block, const int file_
{
switch (va_arg(vlist, int))
{
case sf_normals:
break;
case sf_normals_r:
addr = normalsR_map_.GetBlockRegionAddr(block);
v_normalsR_.at(block).WriteMappedFileRegion(addr);
break;
case sf_atvinv:
break;
case sf_design:
break;
case sf_meas_minus_comp:
addr = measMinusComp_map_.GetBlockRegionAddr(block);
v_measMinusComp_.at(block).WriteMappedFileRegion(addr);
Expand Down Expand Up @@ -395,7 +389,11 @@ void dna_adjust::OpenStageFileStreams(const int file_count, ...)
}

std::stringstream ss;
ss << projectSettings_.g.output_folder << FOLDER_SLASH << projectSettings_.g.network_name << "-";
if (projectSettings_.a.stage_path.empty())
ss << projectSettings_.g.output_folder;
else
ss << projectSettings_.a.stage_path;
ss << FOLDER_SLASH << projectSettings_.g.network_name << "-";
std::string filePath(ss.str());

v_stageFileStreams_.clear();
Expand Down Expand Up @@ -851,6 +849,46 @@ void dna_adjust::OffloadBlockToMappedFile(const UINT32& block)

// Unload block matrix data from memory
UnloadBlock(block);

// Advise kernel that mapped pages for this block are no longer needed,
// freeing page cache for upcoming blocks
AdviseBlockDontNeed(block);
}


void dna_adjust::AdviseBlockDontNeed(const UINT32& block)
{
using advice = boost::interprocess::mapped_region::advice_types;
normalsR_map_.AdviseRegion(block, advice::advice_dontneed);
measMinusComp_map_.AdviseRegion(block, advice::advice_dontneed);
estimatedStations_map_.AdviseRegion(block, advice::advice_dontneed);
originalStations_map_.AdviseRegion(block, advice::advice_dontneed);
rigorousStations_map_.AdviseRegion(block, advice::advice_dontneed);
junctionVariances_map_.AdviseRegion(block, advice::advice_dontneed);
junctionVariancesFwd_map_.AdviseRegion(block, advice::advice_dontneed);
junctionEstimatesFwd_map_.AdviseRegion(block, advice::advice_dontneed);
junctionEstimatesRev_map_.AdviseRegion(block, advice::advice_dontneed);
rigorousVariances_map_.AdviseRegion(block, advice::advice_dontneed);
precAdjMsrs_map_.AdviseRegion(block, advice::advice_dontneed);
corrections_map_.AdviseRegion(block, advice::advice_dontneed);
}


void dna_adjust::AdviseBlockWillNeed(const UINT32& block)
{
using advice = boost::interprocess::mapped_region::advice_types;
normalsR_map_.AdviseRegion(block, advice::advice_willneed);
measMinusComp_map_.AdviseRegion(block, advice::advice_willneed);
estimatedStations_map_.AdviseRegion(block, advice::advice_willneed);
originalStations_map_.AdviseRegion(block, advice::advice_willneed);
rigorousStations_map_.AdviseRegion(block, advice::advice_willneed);
junctionVariances_map_.AdviseRegion(block, advice::advice_willneed);
junctionVariancesFwd_map_.AdviseRegion(block, advice::advice_willneed);
junctionEstimatesFwd_map_.AdviseRegion(block, advice::advice_willneed);
junctionEstimatesRev_map_.AdviseRegion(block, advice::advice_willneed);
rigorousVariances_map_.AdviseRegion(block, advice::advice_willneed);
precAdjMsrs_map_.AdviseRegion(block, advice::advice_willneed);
corrections_map_.AdviseRegion(block, advice::advice_willneed);
}


Expand Down Expand Up @@ -896,7 +934,7 @@ void dna_adjust::UnloadBlock(const UINT32& block, const int file_count, ...)
if (file_count == 0)
{
// deserialise all
UnloadBlock(block, 16,
UnloadBlock(block, 15,
sf_normals, sf_normals_r, sf_atvinv, sf_design, sf_meas_minus_comp,
sf_estimated_stns, sf_original_stns, sf_rigorous_stns,
sf_junction_vars, sf_junction_vars_f, sf_junction_ests_f, sf_junction_ests_r,
Expand All @@ -907,58 +945,60 @@ void dna_adjust::UnloadBlock(const UINT32& block, const int file_count, ...)
va_list vlist;
va_start(vlist, file_count);

// Unload block matrix data from memory
// Unload block matrix data from memory by freeing buffers.
// Use deallocate() instead of explicit destructor calls to keep
// the matrix objects in a valid state for later reuse.
for (UINT16 file(0); file<file_count; ++file)
{
switch (va_arg(vlist, int))
{
case sf_normals:
v_normals_.at(block).~matrix_2d();
v_normals_.at(block).deallocate();
break;
case sf_normals_r:
v_normalsR_.at(block).~matrix_2d();
v_normalsR_.at(block).deallocate();
break;
case sf_atvinv:
v_AtVinv_.at(block).~matrix_2d();
v_AtVinv_.at(block).deallocate();
break;
case sf_design:
v_design_.at(block).~matrix_2d();
v_design_.at(block).deallocate();
break;
case sf_meas_minus_comp:
v_measMinusComp_.at(block).~matrix_2d();
v_measMinusComp_.at(block).deallocate();
break;
case sf_estimated_stns:
v_estimatedStations_.at(block).~matrix_2d();
v_estimatedStations_.at(block).deallocate();
break;
case sf_original_stns:
v_originalStations_.at(block).~matrix_2d();
v_originalStations_.at(block).deallocate();
break;
case sf_rigorous_stns:
v_rigorousStations_.at(block).~matrix_2d();
v_rigorousStations_.at(block).deallocate();
break;
case sf_junction_vars:
v_junctionVariances_.at(block).~matrix_2d();
v_junctionVariances_.at(block).deallocate();
break;
case sf_junction_vars_f:
v_junctionVariancesFwd_.at(block).~matrix_2d();
v_junctionVariancesFwd_.at(block).deallocate();
break;
case sf_junction_ests_f:
v_junctionEstimatesFwd_.at(block).~matrix_2d();
v_junctionEstimatesFwd_.at(block).deallocate();
break;
case sf_junction_ests_r:
v_junctionEstimatesRev_.at(block).~matrix_2d();
v_junctionEstimatesRev_.at(block).deallocate();
break;
case sf_rigorous_vars:
v_rigorousVariances_.at(block).~matrix_2d();
v_rigorousVariances_.at(block).deallocate();
break;
case sf_prec_adj_msrs:
v_precAdjMsrsFull_.at(block).~matrix_2d();
v_precAdjMsrsFull_.at(block).deallocate();
break;
case sf_corrections:
v_corrections_.at(block).~matrix_2d();
v_corrections_.at(block).deallocate();

if (v_blockMeta_.at(block)._blockLast)
v_correctionsR_.at(block).~matrix_2d();
v_correctionsR_.at(block).deallocate();
break;
}
}
Expand Down
Loading
Loading