From 7b71f23d2c6e577de66eddf08a486c574f91b127 Mon Sep 17 00:00:00 2001 From: Wenqing Wang <wenqing.wang@ufz.de> Date: Mon, 13 Nov 2017 17:49:01 +0100 Subject: [PATCH] [PCS] Separate the process variables, BCs and STs by process in class Process --- ProcessLib/Process.cpp | 139 ++++++++++++++++++++++------------------- ProcessLib/Process.h | 49 +++++++++------ 2 files changed, 105 insertions(+), 83 deletions(-) diff --git a/ProcessLib/Process.cpp b/ProcessLib/Process.cpp index ad810458bbe..5eabe1688e9 100644 --- a/ProcessLib/Process.cpp +++ b/ProcessLib/Process.cpp @@ -24,18 +24,28 @@ Process::Process( std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, - std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables, + std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&& + process_variables, SecondaryVariableCollection&& secondary_variables, - NumLib::NamedFunctionCaller&& named_function_caller) + NumLib::NamedFunctionCaller&& named_function_caller, + const bool use_monolithic_scheme) : _mesh(mesh), _secondary_variables(std::move(secondary_variables)), _named_function_caller(std::move(named_function_caller)), _global_assembler(std::move(jacobian_assembler)), - _is_monolithic_scheme(true), + _use_monolithic_scheme(use_monolithic_scheme), _coupled_solutions(nullptr), _integration_order(integration_order), _process_variables(std::move(process_variables)), - _boundary_conditions(parameters) + _boundary_conditions([&]() -> std::vector<BoundaryConditionCollection> { + std::vector<BoundaryConditionCollection> pcs_BCs; + pcs_BCs.reserve(process_variables.size()); + for (std::size_t i = 0; i < process_variables.size(); i++) + { + pcs_BCs.emplace_back(BoundaryConditionCollection(parameters)); + } + return pcs_BCs; + }()) { } @@ -58,56 +68,69 @@ void Process::initialize() finishNamedFunctionsInitialization(); DBUG("Initialize boundary conditions."); - _boundary_conditions.addBCsForProcessVariables( - _process_variables, *_local_to_global_index_map, _integration_order); - - for (int variable_id = 0; - variable_id < static_cast<int>(_process_variables.size()); - ++variable_id) + for (std::size_t pcs_id = 0; pcs_id < _process_variables.size(); pcs_id++) { - ProcessVariable& pv = _process_variables[variable_id]; - auto sts = - pv.createSourceTerms(*_local_to_global_index_map, variable_id, - _integration_order); + auto const& per_process_variables = _process_variables[pcs_id]; + auto& per_process_BCs = _boundary_conditions[pcs_id]; + std::vector<std::unique_ptr<NodalSourceTerm>> per_process_source_terms; + for (std::size_t variable_id = 0; + variable_id < per_process_variables.size(); + variable_id++) + { + per_process_BCs.addBCsForProcessVariables( + per_process_variables, *_local_to_global_index_map, + _integration_order); + + ProcessVariable& pv = per_process_variables[variable_id]; + auto sts = pv.createSourceTerms(*_local_to_global_index_map, 0, + _integration_order); - std::move(sts.begin(), sts.end(), - std::back_inserter(_source_terms)); + std::move(sts.begin(), sts.end(), + std::back_inserter(per_process_source_terms)); + } + _source_terms.push_back(std::move(per_process_source_terms)); } } -void Process::setVariableInitialCondition(const int variable_id, double const t, - GlobalVector& x) +void Process::setInitialConditions(const unsigned pcs_id, double const t, + GlobalVector& x) { - SpatialPosition pos; + auto const& per_process_variables = _process_variables[pcs_id]; + for (std::size_t variable_id = 0; + variable_id < per_process_variables.size(); + variable_id++) + { + SpatialPosition pos; - auto const& pv = _process_variables[variable_id]; - DBUG("Set the initial condition of variable %s.", - pv.get().getName().data()); + auto const& pv = per_process_variables[variable_id]; + DBUG("Set the initial condition of variable %s of process %d.", + pv.get().getName().data(), pcs_id); - auto const& ic = pv.get().getInitialCondition(); + auto const& ic = pv.get().getInitialCondition(); - auto const num_comp = pv.get().getNumberOfComponents(); + auto const num_comp = pv.get().getNumberOfComponents(); - const int mesh_subset_id = _is_monolithic_scheme ? variable_id : 0; + const int mesh_subset_id = _use_monolithic_scheme ? variable_id : 0; - for (int component_id = 0; component_id < num_comp; ++component_id) - { - auto const& mesh_subsets = _local_to_global_index_map->getMeshSubsets( - mesh_subset_id, component_id); - for (auto const& mesh_subset : mesh_subsets) + for (int component_id = 0; component_id < num_comp; ++component_id) { - auto const mesh_id = mesh_subset->getMeshID(); - for (auto const* node : mesh_subset->getNodes()) + auto const& mesh_subsets = + _local_to_global_index_map->getMeshSubsets(mesh_subset_id, + component_id); + for (auto const& mesh_subset : mesh_subsets) { - MeshLib::Location const l(mesh_id, MeshLib::MeshItemType::Node, - node->getID()); - - pos.setNodeID(node->getID()); - auto const& ic_value = ic(t, pos); - - auto global_index = - std::abs(_local_to_global_index_map->getGlobalIndex( - l, mesh_subset_id, component_id)); + auto const mesh_id = mesh_subset->getMeshID(); + for (auto const* node : mesh_subset->getNodes()) + { + MeshLib::Location const l( + mesh_id, MeshLib::MeshItemType::Node, node->getID()); + + pos.setNodeID(node->getID()); + auto const& ic_value = ic(t, pos); + + auto global_index = + std::abs(_local_to_global_index_map->getGlobalIndex( + l, mesh_subset_id, component_id)); #ifdef USE_PETSC // The global indices of the ghost entries of the global // matrix or the global vectors need to be set as negative @@ -120,28 +143,13 @@ void Process::setVariableInitialCondition(const int variable_id, double const t, if (global_index == x.size()) global_index = 0; #endif - x.set(global_index, ic_value[component_id]); + x.set(global_index, ic_value[component_id]); + } } } } } -void Process::setInitialConditions(const unsigned pcs_id, double const t, - GlobalVector& x) -{ - if (!_is_monolithic_scheme) - { - setVariableInitialCondition(pcs_id, t, x); - return; - } - - for (std::size_t variable_id = 0; variable_id < _process_variables.size(); - variable_id++) - { - setVariableInitialCondition(variable_id, t, x); - } -} - MathLib::MatrixSpecifications Process::getMatrixSpecifications() const { auto const& l = *_local_to_global_index_map; @@ -161,9 +169,12 @@ void Process::assemble(const double t, GlobalVector const& x, GlobalMatrix& M, assembleConcreteProcess(t, x, M, K, b); - _boundary_conditions.applyNaturalBC(t, x, K, b); + const auto pcs_id = + (_coupled_solutions) ? _coupled_solutions->process_id : 0; + _boundary_conditions[pcs_id].applyNaturalBC(t, x, K, b); - for (auto const& st : _source_terms) + const auto _source_terms_per_pcs = _source_terms[pcs_id]; + for (auto const& st : _source_terms_per_pcs) { st->integrateNodalSourceTerm(t, b); } @@ -182,7 +193,9 @@ void Process::assembleWithJacobian(const double t, GlobalVector const& x, Jac); // TODO apply BCs to Jacobian. - _boundary_conditions.applyNaturalBC(t, x, K, b); + const auto pcs_id = + (_coupled_solutions) ? _coupled_solutions->process_id : 0; + _boundary_conditions[pcs_id].applyNaturalBC(t, x, K, b); } void Process::constructDofTable() @@ -196,7 +209,7 @@ void Process::constructDofTable() // Vector of the number of variable components std::vector<int> vec_var_n_components; - if (_is_monolithic_scheme) + if (_use_monolithic_scheme) { // Collect the mesh subsets in a vector. for (ProcessVariable const& pv : _process_variables) @@ -243,7 +256,7 @@ void Process::initializeExtrapolator() bool manage_storage; if (_local_to_global_index_map->getNumberOfComponents() == 1 || - !_is_monolithic_scheme) + !_use_monolithic_scheme) { // For single-variable-single-component processes reuse the existing DOF // table. diff --git a/ProcessLib/Process.h b/ProcessLib/Process.h index 39b2cc50b3b..9bdd143265e 100644 --- a/ProcessLib/Process.h +++ b/ProcessLib/Process.h @@ -46,10 +46,11 @@ public: std::unique_ptr<AbstractJacobianAssembler>&& jacobian_assembler, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, - std::vector<std::reference_wrapper<ProcessVariable>>&& + std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&& process_variables, SecondaryVariableCollection&& secondary_variables, - NumLib::NamedFunctionCaller&& named_function_caller); + NumLib::NamedFunctionCaller&& named_function_caller, + const bool use_monolithic_scheme = true); /// Preprocessing before starting assembly for new timestep. void preTimestep(GlobalVector const& x, const double t, @@ -78,14 +79,9 @@ public: _coupled_solutions = coupled_solutions; } - void setDecouplingSchemeType(const bool is_monolithic_scheme) - { - _is_monolithic_scheme = is_monolithic_scheme; - } - bool useMonolithicScheme() const { return _is_monolithic_scheme; } - - virtual void setCoupledSolutionsForStaggeredSchemeToLocalAssemblers() {} + bool isMonolithicSchemeUsed() const { return _use_monolithic_scheme; } + virtual void setCoupledTermForTheStaggeredSchemeToLocalAssemblers() {} void preAssemble(const double t, GlobalVector const& x) override final; void assemble(const double t, GlobalVector const& x, GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b) final; @@ -99,7 +95,9 @@ public: std::vector<NumLib::IndexValueVector<GlobalIndexType>> const* getKnownSolutions(double const t) const final { - return _boundary_conditions.getKnownSolutions(t); + const auto pcs_id = + (_coupled_solutions) ? _coupled_solutions->process_id : 0; + return _boundary_conditions[pcs_id].getKnownSolutions(t); } NumLib::LocalToGlobalIndexMap const& getDOFTable() const @@ -111,7 +109,9 @@ public: std::vector<std::reference_wrapper<ProcessVariable>> const& getProcessVariables() const { - return _process_variables; + const auto pcs_id = + (_coupled_solutions) ? _coupled_solutions->process_id : 0; + return _process_variables[pcs_id]; } SecondaryVariableCollection const& getSecondaryVariables() const @@ -120,6 +120,7 @@ public: } // Get the solution of the previous time step. + virtual GlobalVector* getPreviousTimeStepSolution( const int /*process_id*/) const { @@ -127,6 +128,7 @@ public: } // Used as a call back for CalculateSurfaceFlux process. + virtual std::vector<double> getFlux(std::size_t /*element_id*/, MathLib::Point3d const& /*p*/, GlobalVector const& /*x*/) const @@ -204,9 +206,6 @@ private: /// DOF-table. void computeSparsityPattern(); - void setVariableInitialCondition(const int variable_id, double const t, - GlobalVector& x); - protected: MeshLib::Mesh& _mesh; std::unique_ptr<MeshLib::MeshSubset const> _mesh_subset_all_nodes; @@ -222,7 +221,7 @@ protected: VectorMatrixAssembler _global_assembler; - mutable bool _is_monolithic_scheme; + const bool _use_monolithic_scheme; /// Pointer to CoupledSolutionsForStaggeredScheme, which contains the /// references to the solutions of the coupled processes. @@ -240,11 +239,21 @@ protected: private: GlobalSparsityPattern _sparsity_pattern; - /// Variables used by this process. - std::vector<std::reference_wrapper<ProcessVariable>> _process_variables; - - BoundaryConditionCollection _boundary_conditions; - std::vector<std::unique_ptr<NodalSourceTerm>> _source_terms; + /// Variables used by this process. For the monolithic scheme or a + /// single process, the size of the outer vector is one. For the + /// staggered scheme, the size of the outer vector is the number of the + /// coupled processes. + std::vector<std::vector<std::reference_wrapper<ProcessVariable>>> + _process_variables; + + /// Vector for boundary conditions. For the monolithic scheme or a + /// single process, the size of the vector is one. For the staggered + /// scheme, the size of vector is the number of the coupled processes. + std::vector<BoundaryConditionCollection> _boundary_conditions; + + /// Vector for nodal source terms. The outer vector is for processes, + /// which has the same size as that for boundary conditions. + std::vector<std::vector<std::unique_ptr<NodalSourceTerm>>> _source_terms; ExtrapolatorData _extrapolator_data; }; -- GitLab