diff --git a/ProcessLib/GroundwaterFlowProcess.h b/ProcessLib/GroundwaterFlowProcess.h index b9bbdf2df5a755663683a24f43e788d79e26efe4..c4db0b63676e4e9bc16c6f0f74797c24e45d938f 100644 --- a/ProcessLib/GroundwaterFlowProcess.h +++ b/ProcessLib/GroundwaterFlowProcess.h @@ -11,30 +11,15 @@ #define PROCESS_LIB_GROUNDWATERFLOWPROCESS_H_ #include <cassert> -#include <memory> -#include <boost/algorithm/string/erase.hpp> #include <boost/optional.hpp> - -#include "logog/include/logog.hpp" - #include "AssemblerLib/LocalAssemblerBuilder.h" #include "AssemblerLib/LocalDataInitializer.h" #include "FileIO/VtkIO/VtuInterface.h" -#include "MathLib/LinAlg/ApplyKnownSolution.h" - -#include "MeshLib/MeshSubset.h" -#include "MeshGeoToolsLib/MeshNodeSearcher.h" - -#include "UniformDirichletBoundaryCondition.h" - #include "GroundwaterFlowFEM.h" -#include "NeumannBcAssembler.h" -#include "NeumannBc.h" -#include "DirichletBc.h" #include "Parameter.h" #include "Process.h" @@ -51,8 +36,6 @@ namespace ProcessLib template<typename GlobalSetup> class GroundwaterFlowProcess : public Process<GlobalSetup> { - unsigned const _integration_order = 2; - public: GroundwaterFlowProcess(MeshLib::Mesh& mesh, std::vector<ProcessVariable> const& variables, @@ -80,7 +63,8 @@ public: DBUG("Associate hydraulic_head with process variable \'%s\'.", name.c_str()); - _hydraulic_head = const_cast<ProcessVariable*>(&*variable); + this->_process_variables.emplace_back( + const_cast<ProcessVariable*>(&*variable)); } // Hydraulic conductivity parameter. @@ -152,51 +136,7 @@ public: this->_mesh.getElements(), _local_assemblers, *_hydraulic_conductivity, - _integration_order); - - DBUG("Initialize boundary conditions."); - MeshGeoToolsLib::MeshNodeSearcher& hydraulic_head_mesh_node_searcher = - MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher( - _hydraulic_head->getMesh()); - - _hydraulic_head->initializeDirichletBCs( - std::back_inserter(_dirichlet_bcs), - hydraulic_head_mesh_node_searcher, - *this->_local_to_global_index_map, - 0); - - // - // Neumann boundary conditions. - // - { - // Find mesh nodes. - MeshGeoToolsLib::BoundaryElementsSearcher hydraulic_head_mesh_element_searcher( - _hydraulic_head->getMesh(), hydraulic_head_mesh_node_searcher); - - // Create a neumann BC for the hydraulic head storing them in the - // _neumann_bcs vector. - _hydraulic_head->createNeumannBcs( - std::back_inserter(_neumann_bcs), - hydraulic_head_mesh_element_searcher, - this->_global_setup, - _integration_order, - *this->_local_to_global_index_map, - 0, - *_mesh_subset_all_nodes); - } - - Process<GlobalSetup>::initializeNeumannBcs(_neumann_bcs); - } - - void initializeMeshSubsets(MeshLib::Mesh const& mesh) override - { - // Create single component dof in every of the mesh's nodes. - _mesh_subset_all_nodes = - new MeshLib::MeshSubset(mesh, &mesh.getNodes()); - - // Collect the mesh subsets in a vector. - this->_all_mesh_subsets.push_back( - new MeshLib::MeshSubsets(_mesh_subset_all_nodes)); + this->_integration_order); } std::string getLinearSolverName() const override @@ -204,12 +144,8 @@ public: return "gw_"; } - void init() override + void createLocalAssemblers() override { - DBUG("Initialize GroundwaterFlowProcess."); - - Process<GlobalSetup>::setInitialConditions(*_hydraulic_head, 0); - if (this->_mesh.getDimension()==1) createLocalAssemblers<1>(); else if (this->_mesh.getDimension()==2) @@ -230,14 +166,6 @@ public: this->_global_setup.execute(*this->_global_assembler, _local_assemblers); - // Call global assembler for each Neumann boundary local assembler. - for (auto bc : _neumann_bcs) - bc->integrate(this->_global_setup); - - for (auto const& bc : _dirichlet_bcs) - MathLib::applyKnownSolution(*this->_A, *this->_rhs, *this->_x, - bc.global_ids, bc.values); - return true; } @@ -294,29 +222,17 @@ public: ~GroundwaterFlowProcess() { - for (auto p : _neumann_bcs) - delete p; - for (auto p : _local_assemblers) delete p; - - delete _mesh_subset_all_nodes; } private: - ProcessVariable* _hydraulic_head = nullptr; - Parameter<double, MeshLib::Element const&> const* _hydraulic_conductivity = nullptr; - MeshLib::MeshSubset const* _mesh_subset_all_nodes = nullptr; - using LocalAssembler = GroundwaterFlow::LocalAssemblerDataInterface< typename GlobalSetup::MatrixType, typename GlobalSetup::VectorType>; std::vector<LocalAssembler*> _local_assemblers; - - std::vector<DirichletBc<GlobalIndexType>> _dirichlet_bcs; - std::vector<NeumannBc<GlobalSetup>*> _neumann_bcs; }; } // namespace ProcessLib diff --git a/ProcessLib/Process.h b/ProcessLib/Process.h index 9de6e4ac5a50206e2377a2bb7861c542afc18681..fc86eb09239410556da60805634f067c2e64dc10 100644 --- a/ProcessLib/Process.h +++ b/ProcessLib/Process.h @@ -10,13 +10,20 @@ #ifndef PROCESS_LIB_PROCESS_H_ #define PROCESS_LIB_PROCESS_H_ +#include <memory> #include <string> +#include <logog/include/logog.hpp> + + #include "AssemblerLib/ComputeSparsityPattern.h" -#include "AssemblerLib/VectorMatrixAssembler.h" #include "AssemblerLib/LocalToGlobalIndexMap.h" +#include "AssemblerLib/VectorMatrixAssembler.h" #include "BaseLib/ConfigTreeNew.h" +#include "MathLib/LinAlg/ApplyKnownSolution.h" #include "MathLib/LinAlg/SetMatrixSparsity.h" +#include "MeshGeoToolsLib/MeshNodeSearcher.h" +#include "MeshLib/MeshSubset.h" #include "MeshLib/MeshSubsets.h" #ifdef USE_PETSC @@ -24,7 +31,11 @@ #include "MathLib/LinAlg/PETSc/PETScMatrixOption.h" #endif +#include "DirichletBc.h" +#include "NeumannBc.h" +#include "NeumannBcAssembler.h" #include "ProcessVariable.h" +#include "UniformDirichletBoundaryCondition.h" namespace MeshLib { @@ -42,10 +53,11 @@ public: { for (auto p : _all_mesh_subsets) delete p; + delete _mesh_subset_all_nodes; } /// Process specific initialization called by initialize(). - virtual void init() = 0; + virtual void createLocalAssemblers() = 0; virtual bool assemble(const double delta_t) = 0; virtual std::string getLinearSolverName() const = 0; @@ -56,15 +68,12 @@ public: virtual void postTimestep(std::string const& file_name, const unsigned timestep) = 0; - /// Creates mesh subsets, i.e. components, for given mesh. - virtual void initializeMeshSubsets(MeshLib::Mesh const& mesh) = 0; - void initialize() { DBUG("Initialize process."); DBUG("Construct dof mappings."); - initializeMeshSubsets(_mesh); + initializeMeshSubsets(); _local_to_global_index_map.reset( new AssemblerLib::LocalToGlobalIndexMap( @@ -82,12 +91,20 @@ public: _global_assembler.reset( new GlobalAssembler(*_A, *_rhs, *_local_to_global_index_map)); - init(); // Execute proces specific initialization. - } + createLocalAssemblers(); - void initializeNeumannBcs(std::vector<NeumannBc<GlobalSetup>*> const& bcs) - { - for (auto bc : bcs) + for (auto const& pv : _process_variables) + { + DBUG("Set initial conditions."); + setInitialConditions(*pv, 0); // 0 is the component id + + DBUG("Initialize boundary conditions."); + createDirichletBcs(*pv, 0); // 0 is the component id + + createNeumannBcs(*pv, 0); // 0 is the component id + } + + for (auto& bc : _neumann_bcs) bc->initialize(_global_setup, *_A, *_rhs, _mesh.getDimension()); } @@ -98,6 +115,14 @@ public: bool const result = assemble(delta_t); + // Call global assembler for each Neumann boundary local assembler. + for (auto const& bc : _neumann_bcs) + bc->integrate(_global_setup); + + for (auto const& bc : _dirichlet_bcs) + MathLib::applyKnownSolution(*_A, *_rhs, *_x, + bc.global_ids, bc.values); + _linear_solver->solve(*_rhs, *_x); return result; } @@ -111,6 +136,19 @@ protected: std::move(config))); } +private: + /// Creates mesh subsets, i.e. components, for given mesh. + void initializeMeshSubsets() + { + // Create single component dof in every of the mesh's nodes. + _mesh_subset_all_nodes = + new MeshLib::MeshSubset(_mesh, &_mesh.getNodes()); + + // Collect the mesh subsets in a vector. + _all_mesh_subsets.push_back( + new MeshLib::MeshSubsets(_mesh_subset_all_nodes)); + } + /// Sets the initial condition values in the solution vector x for a given /// process variable and component. void setInitialConditions(ProcessVariable const& variable, @@ -128,7 +166,39 @@ protected: } } -private: + void createDirichletBcs(ProcessVariable& variable, + int const component_id) + { + MeshGeoToolsLib::MeshNodeSearcher& mesh_node_searcher = + MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher( + variable.getMesh()); + + variable.initializeDirichletBCs(std::back_inserter(_dirichlet_bcs), + mesh_node_searcher, + *_local_to_global_index_map, + component_id); + } + + void createNeumannBcs(ProcessVariable& variable, int const component_id) + { + // Find mesh nodes. + MeshGeoToolsLib::MeshNodeSearcher& mesh_node_searcher = + MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher( + variable.getMesh()); + MeshGeoToolsLib::BoundaryElementsSearcher mesh_element_searcher( + variable.getMesh(), mesh_node_searcher); + + // Create a neumann BC for the process variable storing them in the + // _neumann_bcs vector. + variable.createNeumannBcs(std::back_inserter(_neumann_bcs), + mesh_element_searcher, + _global_setup, + _integration_order, + *_local_to_global_index_map, + component_id, + *_mesh_subset_all_nodes); + } + /// Creates global matrix, rhs and solution vectors, and the linear solver. void createLinearSolver(std::string const& solver_name) { @@ -162,7 +232,10 @@ private: } protected: + unsigned const _integration_order = 2; + MeshLib::Mesh& _mesh; + MeshLib::MeshSubset const* _mesh_subset_all_nodes = nullptr; std::vector<MeshLib::MeshSubsets*> _all_mesh_subsets; GlobalSetup _global_setup; @@ -184,6 +257,12 @@ protected: std::unique_ptr<typename GlobalSetup::VectorType> _x; AssemblerLib::SparsityPattern _sparsity_pattern; + + std::vector<DirichletBc<GlobalIndexType>> _dirichlet_bcs; + std::vector<std::unique_ptr<NeumannBc<GlobalSetup>>> _neumann_bcs; + + /// Variables used by this process. + std::vector<ProcessVariable*> _process_variables; }; } // namespace ProcessLib diff --git a/ProcessLib/ProcessVariable.h b/ProcessLib/ProcessVariable.h index f67506765f04301d32c642058ceb3feacfff25ec..565768a807075e5a47bef920bd8d4e1b696f4d2a 100644 --- a/ProcessLib/ProcessVariable.h +++ b/ProcessLib/ProcessVariable.h @@ -81,8 +81,9 @@ public: for (auto& config : _neumann_bc_configs) { config->initialize(searcher); - bcs++ = new NeumannBc<GlobalSetup>(*config, - std::forward<Args>(args)...); + bcs++ = std::unique_ptr<NeumannBc<GlobalSetup>>{ + new NeumannBc<GlobalSetup>(*config, + std::forward<Args>(args)...)}; } }