/** * \copyright * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license * * \file * * Created on August 19, 2016, 1:38 PM */ #include "LiquidFlowProcess.h" #include #include "LiquidFlowLocalAssembler.h" #include "MathLib/LinAlg/FinalizeMatrixAssembly.h" #include "MathLib/LinAlg/FinalizeVectorAssembly.h" #include "MeshLib/PropertyVector.h" #include "ProcessLib/Utils/ComputeResiduum.h" #include "ProcessLib/Utils/CreateLocalAssemblers.h" namespace ProcessLib { namespace LiquidFlow { LiquidFlowProcess::LiquidFlowProcess( std::string name, MeshLib::Mesh& mesh, std::unique_ptr&& jacobian_assembler, std::vector> const& parameters, unsigned const integration_order, std::vector>>&& process_variables, LiquidFlowData&& process_data, SecondaryVariableCollection&& secondary_variables, std::unique_ptr&& surfaceflux) : Process(std::move(name), mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables)), _process_data(std::move(process_data)), _surfaceflux(std::move(surfaceflux)) { DBUG("Create Liquid flow process."); _hydraulic_flow = MeshLib::getOrCreateMeshProperty( mesh, "HydraulicFlow", MeshLib::MeshItemType::Node, 1); } void LiquidFlowProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { const int process_id = 0; ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; ProcessLib::createLocalAssemblers( mesh.getDimension(), mesh.getElements(), dof_table, pv.getShapeFunctionOrder(), _local_assemblers, mesh.isAxiallySymmetric(), integration_order, _process_data); _secondary_variables.addSecondaryVariable( "darcy_velocity", makeExtrapolator( mesh.getDimension(), getExtrapolator(), _local_assemblers, &LiquidFlowLocalAssemblerInterface::getIntPtDarcyVelocity)); } void LiquidFlowProcess::assembleConcreteProcess( const double t, double const dt, std::vector const& x, std::vector const& xdot, int const process_id, GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b) { DBUG("Assemble LiquidFlowProcess."); std::vector> dof_table = {std::ref(*_local_to_global_index_map)}; ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; // Call global assembler for each local assembly item. GlobalExecutor::executeSelectedMemberDereferenced( _global_assembler, &VectorMatrixAssembler::assemble, _local_assemblers, pv.getActiveElementIDs(), dof_table, t, dt, x, xdot, process_id, M, K, b); MathLib::finalizeMatrixAssembly(M); MathLib::finalizeMatrixAssembly(K); MathLib::finalizeVectorAssembly(b); auto const residuum = computeResiduum(*x[0], *xdot[0], M, K, b); transformVariableFromGlobalVector(residuum, 0 /*variable id*/, *_local_to_global_index_map, *_hydraulic_flow, std::negate()); } void LiquidFlowProcess::assembleWithJacobianConcreteProcess( const double t, double const dt, std::vector const& x, std::vector const& xdot, const double dxdot_dx, const double dx_dx, int const process_id, GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b, GlobalMatrix& Jac) { DBUG("AssembleWithJacobian LiquidFlowProcess."); std::vector> dof_table = {std::ref(*_local_to_global_index_map)}; ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; // Call global assembler for each local assembly item. GlobalExecutor::executeSelectedMemberDereferenced( _global_assembler, &VectorMatrixAssembler::assembleWithJacobian, _local_assemblers, pv.getActiveElementIDs(), dof_table, t, dt, x, xdot, dxdot_dx, dx_dx, process_id, M, K, b, Jac); } void LiquidFlowProcess::computeSecondaryVariableConcrete( double const t, double const dt, std::vector const& x, GlobalVector const& x_dot, int const process_id) { DBUG("Compute the velocity for LiquidFlowProcess."); std::vector dof_tables; dof_tables.reserve(x.size()); std::generate_n(std::back_inserter(dof_tables), x.size(), [&]() { return _local_to_global_index_map.get(); }); ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; GlobalExecutor::executeSelectedMemberOnDereferenced( &LiquidFlowLocalAssemblerInterface::computeSecondaryVariable, _local_assemblers, pv.getActiveElementIDs(), dof_tables, t, dt, x, x_dot, process_id); } Eigen::Vector3d LiquidFlowProcess::getFlux( std::size_t const element_id, MathLib::Point3d const& p, double const t, std::vector const& x) const { // fetch local_x from primary variable std::vector indices_cache; auto const r_c_indices = NumLib::getRowColumnIndices( element_id, *_local_to_global_index_map, indices_cache); constexpr int process_id = 0; // monolithic scheme. std::vector local_x(x[process_id]->get(r_c_indices.rows)); return _local_assemblers[element_id]->getFlux(p, t, local_x); } // this is almost a copy of the implementation in the GroundwaterFlow void LiquidFlowProcess::postTimestepConcreteProcess( std::vector const& x, const double t, const double /*dt*/, int const process_id) { if (!_surfaceflux) // computing the surfaceflux is optional { return; } ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; _surfaceflux->integrate(x, t, *this, process_id, _integration_order, _mesh, pv.getActiveElementIDs()); } } // namespace LiquidFlow } // namespace ProcessLib