diff --git a/Documentation/ProjectFile/prj/processes/process/HEAT_TRANSPORT_BHE/t_linear.md b/Documentation/ProjectFile/prj/processes/process/HEAT_TRANSPORT_BHE/t_linear.md index c75385a76ff80457576de35b754ec7e101b37a07..0f48474050f1cd6acf89a1e5db41ecc3acdf488c 100644 --- a/Documentation/ProjectFile/prj/processes/process/HEAT_TRANSPORT_BHE/t_linear.md +++ b/Documentation/ProjectFile/prj/processes/process/HEAT_TRANSPORT_BHE/t_linear.md @@ -1 +1,5 @@ -The default setting is false. When activated, non-linear iterations will be turned off. The simulation will just go through a single iteration within a time step. If it's set to true, the **\<use_algebraic_bc\>** option must be also set to true. Only when fluid properties does not change much with temperature, this feature can be activated. The effect of skipping the non-linear iteration is much faster simulation speed. +The default setting is false. When activated, non-linear iterations will be turned off and the equation system for the soil part is only assembled once. +If the `<use_algebraic_bc>` option is also set to true, the simulation will just go through a single iteration within a time step. +Otherwise iterations are needed to fulfill the boundary conditions of the BHE. +Only when fluid properties do not change much with temperature, this feature can be activated. +The effect of skipping the non-linear iteration is much faster simulation speed. diff --git a/ProcessLib/HeatTransportBHE/CreateHeatTransportBHEProcess.cpp b/ProcessLib/HeatTransportBHE/CreateHeatTransportBHEProcess.cpp index bd724ac17b92656bba0ac3a22cbca16d5edbf1b3..eb2f140287495b8e337b46b3baff2b5c47bac2b0 100644 --- a/ProcessLib/HeatTransportBHE/CreateHeatTransportBHEProcess.cpp +++ b/ProcessLib/HeatTransportBHE/CreateHeatTransportBHEProcess.cpp @@ -195,10 +195,15 @@ std::unique_ptr<Process> createHeatTransportBHEProcess( { if (!using_algebraic_bc) { - OGS_FATAL( + WARN( "You specified that the process simulated by OGS is linear. " - "For the Heat-Transport-BHE process this can only be done " - "together with setting the use_algebraic_bc option to true.") + "With that optimization the process will be assembled only " + "once and the non-linear solver will only do iterations per " + "time step to fulfill the BHE boundary conditions. No other " + "non-linearities will be resolved and OGS will not detect if " + "there are any non-linearities. It is your responsibility to " + "ensure that the assembled equation systems are linear, " + "indeed! There is no safety net!"); } else { @@ -336,7 +341,7 @@ std::unique_ptr<Process> createHeatTransportBHEProcess( HeatTransportBHEProcessData process_data( std::move(media_map), std::move(bhes), py_object, using_tespy, using_server_communication, mass_lumping, - {using_algebraic_bc, weighting_factor, is_linear}); + {using_algebraic_bc, weighting_factor}, is_linear); SecondaryVariableCollection secondary_variables; diff --git a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.cpp b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.cpp index 8528005f6f38feb56bb55c01295c9619fee6265e..576aad5db10d7ab6d73bd7105d3edff9ea93bc61 100644 --- a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.cpp +++ b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.cpp @@ -14,6 +14,7 @@ #include "BoundaryConditions/BHEBottomDirichletBoundaryCondition.h" #include "BoundaryConditions/BHEInflowDirichletBoundaryCondition.h" +#include "MathLib/LinAlg/SetMatrixSparsity.h" #include "MeshLib/MeshSearch/ElementSearch.h" #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/BHEInflowPythonBoundaryCondition.h" #include "ProcessLib/HeatTransportBHE/BHE/MeshUtils.h" @@ -40,7 +41,8 @@ HeatTransportBHEProcess::HeatTransportBHEProcess( integration_order, std::move(process_variables), std::move(secondary_variables)), _process_data(std::move(process_data)), - _bheMeshData(std::move(bhe_mesh_data)) + _bheMeshData(std::move(bhe_mesh_data)), + _asm_mat_cache{_process_data._is_linear, true /*use_monolithic_scheme*/} { if (_bheMeshData.BHE_mat_IDs.size() != _process_data._vec_BHE_property.size()) @@ -159,6 +161,33 @@ void HeatTransportBHEProcess::initializeConcreteProcess( // Create BHE boundary conditions for each of the BHEs createBHEBoundaryConditionTopBottom(_bheMeshData.BHE_nodes); + // Store BHE and soil elements to split the assembly and use the matrix + // cache in the linear case only for soil elements + if (_process_data._is_linear) + { + _bhes_element_ids = _bheMeshData.BHE_elements | ranges::views::join | + MeshLib::views::ids | ranges::to<std::vector>; + + // sort bhe elements if needed + if (!std::is_sorted(_bhes_element_ids.begin(), _bhes_element_ids.end())) + { + std::sort(_bhes_element_ids.begin(), _bhes_element_ids.end()); + } + + _soil_element_ids = mesh.getElements() | MeshLib::views::ids | + ranges::to<std::vector>(); + + // sort soil elements if needed + if (!std::is_sorted(_soil_element_ids.begin(), _soil_element_ids.end())) + { + std::sort(_soil_element_ids.begin(), _soil_element_ids.end()); + } + + _soil_element_ids = ranges::views::set_difference(_soil_element_ids, + _bhes_element_ids) | + ranges::to<std::vector>(); + } + if (_process_data._mass_lumping) { std::vector<std::size_t> const bhes_node_ids = @@ -190,11 +219,42 @@ void HeatTransportBHEProcess::assembleConcreteProcess( std::vector<NumLib::LocalToGlobalIndexMap const*> dof_table = { _local_to_global_index_map.get()}; - // Call global assembler for each local assembly item. - GlobalExecutor::executeSelectedMemberDereferenced( - _global_assembler, &VectorMatrixAssembler::assemble, _local_assemblers, - getActiveElementIDs(), dof_table, t, dt, x, x_prev, process_id, &M, &K, - &b); + + if (_process_data._is_linear) + { + if (!getActiveElementIDs().empty()) + { + OGS_FATAL( + "Domain Deactivation is currently not implemnted with " + "linear optimization."); + } + + auto const& spec = getMatrixSpecifications(process_id); + + // use matrix cache for soil elements + _asm_mat_cache.assemble(t, dt, x, x_prev, process_id, &M, &K, &b, + dof_table, _global_assembler, _local_assemblers, + _soil_element_ids); + + // reset the sparsity pattern for better performance in the BHE assembly + MathLib::setMatrixSparsity(M, *spec.sparsity_pattern); + MathLib::setMatrixSparsity(K, *spec.sparsity_pattern); + + // Call global assembler for each local BHE assembly item. + GlobalExecutor::executeSelectedMemberDereferenced( + _global_assembler, &VectorMatrixAssembler::assemble, + _local_assemblers, _bhes_element_ids, dof_table, t, dt, x, x_prev, + process_id, &M, &K, &b); + } + else + { + // Call global assembler for each local assembly item. + GlobalExecutor::executeSelectedMemberDereferenced( + _global_assembler, &VectorMatrixAssembler::assemble, + _local_assemblers, getActiveElementIDs(), dof_table, t, dt, x, + x_prev, process_id, &M, &K, &b); + } + // Algebraic BC procedure. if (_process_data._algebraic_BC_Setting._use_algebraic_bc) { diff --git a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.h b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.h index 5ee4be7f1a3fe312366faf6f38498e8d1c553c57..e3090e51e72d9f3eae9037f8cd60d4712d177fa1 100644 --- a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.h +++ b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcess.h @@ -11,6 +11,7 @@ #pragma once #include "HeatTransportBHEProcessData.h" +#include "ProcessLib/Assembly/AssembledMatrixCache.h" #include "ProcessLib/HeatTransportBHE/BHE/MeshUtils.h" #include "ProcessLib/HeatTransportBHE/LocalAssemblers/HeatTransportBHEProcessAssemblerInterface.h" #include "ProcessLib/Process.h" @@ -42,7 +43,10 @@ public: //! @{ bool isLinear() const override { - return _process_data._algebraic_BC_Setting._is_linear; + // Linear Solver is called only once - valid only with + // _use_algebraic_bc and _is_linear + return _process_data._algebraic_BC_Setting._use_algebraic_bc && + _process_data._is_linear; } bool requiresNormalization() const override @@ -123,6 +127,12 @@ private: std::unique_ptr<MeshLib::MeshSubset const> _mesh_subset_soil_nodes; const BHEMeshData _bheMeshData; + + AssembledMatrixCache _asm_mat_cache; + + std::vector<std::size_t> _bhes_element_ids; + + std::vector<std::size_t> _soil_element_ids; }; } // namespace HeatTransportBHE } // namespace ProcessLib diff --git a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcessData.h b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcessData.h index bb612187da7e71cab7b1106e324dce3223258d3b..f733bd945fabd6b3046644293842728d85c37c86 100644 --- a/ProcessLib/HeatTransportBHE/HeatTransportBHEProcessData.h +++ b/ProcessLib/HeatTransportBHE/HeatTransportBHEProcessData.h @@ -28,8 +28,6 @@ struct AlgebraicBCSetting const bool _use_algebraic_bc; const double _weighting_factor; - - const bool _is_linear; }; struct HeatTransportBHEProcessData final @@ -42,14 +40,16 @@ struct HeatTransportBHEProcessData final const bool use_tespy = false, const bool use_server_communication = false, const bool mass_lumping = false, - AlgebraicBCSetting algebraicBCSetting = {false, 100.0, false}) + AlgebraicBCSetting algebraicBCSetting = {false, 100.0}, + const bool is_linear = false) : media_map(media_map_), _vec_BHE_property(std::move(vec_BHEs_)), py_bc_object(py_bc_object_), _use_tespy(use_tespy), _use_server_communication(use_server_communication), _mass_lumping(mass_lumping), - _algebraic_BC_Setting(algebraicBCSetting) + _algebraic_BC_Setting(algebraicBCSetting), + _is_linear(is_linear) { } MaterialPropertyLib::MaterialSpatialDistributionMap media_map; @@ -71,5 +71,7 @@ struct HeatTransportBHEProcessData final std::vector<bool> mass_lumping_soil_elements; AlgebraicBCSetting const _algebraic_BC_Setting; + + const bool _is_linear; }; } // namespace ProcessLib::HeatTransportBHE diff --git a/ProcessLib/HeatTransportBHE/Tests.cmake b/ProcessLib/HeatTransportBHE/Tests.cmake index 028d97295a5d76783ba2507fbd74daed07696b38..e14b64133f27cc99c59f4408ddfa7d2051a0c63d 100644 --- a/ProcessLib/HeatTransportBHE/Tests.cmake +++ b/ProcessLib/HeatTransportBHE/Tests.cmake @@ -12,6 +12,20 @@ AddTest( sandwich_ts_10_t_600.000000.vtu sandwich_ts_10_t_600.000000.vtu temperature_soil temperature_soil 0 1e-13 ) +AddTest( + NAME HeatTransportBHE_1U_3D_bhe_sandwich_linear + PATH Parabolic/T/3D_BHE_Sandwich + EXECUTABLE ogs + EXECUTABLE_ARGS sandwich_linear.xml + WRAPPER time + TESTER vtkdiff + REQUIREMENTS NOT OGS_USE_MPI + RUNTIME 10 + DIFF_DATA + sandwich_ts_10_t_600.000000.vtu sandwich_linear_ts_10_t_600.000000.vtu temperature_BHE1 temperature_BHE1 0 5e-15 + sandwich_ts_10_t_600.000000.vtu sandwich_linear_ts_10_t_600.000000.vtu temperature_soil temperature_soil 0 1e-13 +) + AddTest( NAME HeatTransportBHE_1U_3D_bhe_sandwich_Newton PATH Parabolic/T/3D_BHE_Sandwich @@ -110,6 +124,20 @@ AddTest( beier_sandbox_ts_10_t_600.000000.vtu beier_sandbox_ts_10_t_600.000000.vtu temperature_soil temperature_soil 0 1e-13 ) +AddTest( + NAME HeatTransportBHE_1U_3D_beier_sandbox_linear + PATH Parabolic/T/3D_Beier_sandbox + EXECUTABLE ogs + EXECUTABLE_ARGS beier_sandbox_linear.xml + WRAPPER time + TESTER vtkdiff + REQUIREMENTS NOT OGS_USE_MPI + RUNTIME 20 + DIFF_DATA + beier_sandbox_ts_10_t_600.000000.vtu beier_sandbox_linear_ts_10_t_600.000000.vtu temperature_BHE1 temperature_BHE1 0 5e-15 + beier_sandbox_ts_10_t_600.000000.vtu beier_sandbox_linear_ts_10_t_600.000000.vtu temperature_soil temperature_soil 0 1e-13 +) + AddTest( NAME HeatTransportBHE_1U_3D_beier_sandbox_Newton PATH Parabolic/T/3D_Beier_sandbox diff --git a/Tests/Data/Parabolic/T/3D_BHE_Sandwich/sandwich_linear.xml b/Tests/Data/Parabolic/T/3D_BHE_Sandwich/sandwich_linear.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea5dbd1dd6934a3398361fcd83303a0f8bc6040e --- /dev/null +++ b/Tests/Data/Parabolic/T/3D_BHE_Sandwich/sandwich_linear.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<OpenGeoSysProjectDiff base_file="sandwich.prj"> + <add sel="/*/processes/process"> + <linear>true</linear> + </add> + <replace sel="/*/time_loop/output/prefix/text()">sandwich_linear</replace> +</OpenGeoSysProjectDiff> diff --git a/Tests/Data/Parabolic/T/3D_Beier_sandbox/beier_sandbox_linear.xml b/Tests/Data/Parabolic/T/3D_Beier_sandbox/beier_sandbox_linear.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f2c741bb14d60019b584afd4d589a0d98910b29 --- /dev/null +++ b/Tests/Data/Parabolic/T/3D_Beier_sandbox/beier_sandbox_linear.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<OpenGeoSysProjectDiff base_file="beier_sandbox.prj"> + <add sel="/*/processes/process"> + <linear>true</linear> + </add> + <replace sel="/*/time_loop/output/prefix/text()">beier_sandbox_linear</replace> +</OpenGeoSysProjectDiff>