Forked from
ogs / ogs
16441 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
VectorMatrixAssembler.cpp 8.21 KiB
/**
* \copyright
* Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "VectorMatrixAssembler.h"
#include <cassert>
#include <functional> // for std::reference_wrapper.
#include "NumLib/DOF/DOFTableUtil.h"
#include "MathLib/LinAlg/Eigen/EigenMapTools.h"
#include "LocalAssemblerInterface.h"
#include "CoupledSolutionsForStaggeredScheme.h"
#include "Process.h"
namespace ProcessLib
{
VectorMatrixAssembler::VectorMatrixAssembler(
std::unique_ptr<AbstractJacobianAssembler>&& jacobian_assembler)
: _jacobian_assembler(std::move(jacobian_assembler))
{
}
void VectorMatrixAssembler::preAssemble(
const std::size_t mesh_item_id, LocalAssemblerInterface& local_assembler,
const NumLib::LocalToGlobalIndexMap& dof_table, const double t,
const GlobalVector& x)
{
auto const indices = NumLib::getIndices(mesh_item_id, dof_table);
auto const local_x = x.get(indices);
local_assembler.preAssemble(t, local_x);
}
void VectorMatrixAssembler::assemble(
const std::size_t mesh_item_id, LocalAssemblerInterface& local_assembler,
const NumLib::LocalToGlobalIndexMap& dof_table, const double t,
const GlobalVector& x, GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b,
const CoupledSolutionsForStaggeredScheme* cpl_xs)
{
auto const indices = NumLib::getIndices(mesh_item_id, dof_table);
_local_M_data.clear();
_local_K_data.clear();
_local_b_data.clear();
if (cpl_xs == nullptr)
{
auto const local_x = x.get(indices);
local_assembler.assemble(t, local_x, _local_M_data, _local_K_data,
_local_b_data);
}
else
{
std::vector<std::reference_wrapper<const std::vector<GlobalIndexType>>>
indices_of_all_coupled_processes;
indices_of_all_coupled_processes.reserve(cpl_xs->coupled_xs.size());
for (std::size_t i = 0; i < cpl_xs->coupled_xs.size(); i++)
{
indices_of_all_coupled_processes.emplace_back(std::ref(indices));
}
auto local_coupled_xs0 = getPreviousLocalSolutions(
*cpl_xs, indices_of_all_coupled_processes);
auto local_coupled_xs =
getCurrentLocalSolutions(*cpl_xs, indices_of_all_coupled_processes);
ProcessLib::LocalCoupledSolutions local_coupled_solutions(
cpl_xs->dt, cpl_xs->process_id, std::move(local_coupled_xs0),
std::move(local_coupled_xs));
local_assembler.assembleForStaggeredScheme(t, _local_M_data,
_local_K_data, _local_b_data,
local_coupled_solutions);
}
auto const num_r_c = indices.size();
auto const r_c_indices =
NumLib::LocalToGlobalIndexMap::RowColumnIndices(indices, indices);
if (!_local_M_data.empty())
{
auto const local_M = MathLib::toMatrix(_local_M_data, num_r_c, num_r_c);
M.add(r_c_indices, local_M);
}
if (!_local_K_data.empty())
{
auto const local_K = MathLib::toMatrix(_local_K_data, num_r_c, num_r_c);
K.add(r_c_indices, local_K);
}
if (!_local_b_data.empty())
{
assert(_local_b_data.size() == num_r_c);
b.add(indices, _local_b_data);
}
}
void VectorMatrixAssembler::assembleWithJacobian(
std::size_t const mesh_item_id, LocalAssemblerInterface& local_assembler,
NumLib::LocalToGlobalIndexMap const& dof_table, const double t,
GlobalVector const& x, GlobalVector const& xdot, const double dxdot_dx,
const double dx_dx, GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b,
GlobalMatrix& Jac, const CoupledSolutionsForStaggeredScheme* cpl_xs,
NumLib::LocalToGlobalIndexMap const* base_dof_table)
{
// If base_dof_table != nullptr, then the coupled processes contains the
// mechanical process, which is alway placed in the end of the coupled
// process and always user higher order element than other process in the
// coupling.
auto const indices =
((base_dof_table == nullptr) ||
(cpl_xs->process_id ==
static_cast<int>(cpl_xs->coupled_xs.size()) - 1 &&
cpl_xs != nullptr))
? NumLib::getIndices(mesh_item_id, dof_table)
: NumLib::getIndices(mesh_item_id, *base_dof_table);
auto const local_xdot = xdot.get(indices);
_local_M_data.clear();
_local_K_data.clear();
_local_b_data.clear();
_local_Jac_data.clear();
if (cpl_xs == nullptr)
{
auto const local_x = x.get(indices);
_jacobian_assembler->assembleWithJacobian(
local_assembler, t, local_x, local_xdot, dxdot_dx, dx_dx,
_local_M_data, _local_K_data, _local_b_data, _local_Jac_data);
}
else
{
if (base_dof_table == nullptr)
{
local_assembleWithJacobianForStaggeredScheme(
t, indices, indices, local_xdot, local_assembler, dxdot_dx,
dx_dx, cpl_xs);
}
else
{
if (cpl_xs->process_id ==
static_cast<int>(cpl_xs->coupled_xs.size()) - 1)
{
const auto base_indices =
NumLib::getIndices(mesh_item_id, *base_dof_table);
local_assembleWithJacobianForStaggeredScheme(
t, base_indices, indices, local_xdot, local_assembler,
dxdot_dx, dx_dx, cpl_xs);
}
else
{
const auto full_indices =
NumLib::getIndices(mesh_item_id, dof_table);
local_assembleWithJacobianForStaggeredScheme(
t, indices, full_indices, local_xdot, local_assembler,
dxdot_dx, dx_dx, cpl_xs);
}
}
}
auto const num_r_c = indices.size();
auto const r_c_indices =
NumLib::LocalToGlobalIndexMap::RowColumnIndices(indices, indices);
if (!_local_M_data.empty())
{
auto const local_M = MathLib::toMatrix(_local_M_data, num_r_c, num_r_c);
M.add(r_c_indices, local_M);
}
if (!_local_K_data.empty())
{
auto const local_K = MathLib::toMatrix(_local_K_data, num_r_c, num_r_c);
K.add(r_c_indices, local_K);
}
if (!_local_b_data.empty())
{
assert(_local_b_data.size() == num_r_c);
b.add(indices, _local_b_data);
}
if (!_local_Jac_data.empty())
{
auto const local_Jac =
MathLib::toMatrix(_local_Jac_data, num_r_c, num_r_c);
Jac.add(r_c_indices, local_Jac);
}
else
{
OGS_FATAL(
"No Jacobian has been assembled! This might be due to programming "
"errors in the local assembler of the current process.");
}
}
void VectorMatrixAssembler::local_assembleWithJacobianForStaggeredScheme(
const double t, std::vector<GlobalIndexType> const& base_indices,
std::vector<GlobalIndexType> const& full_indices,
std::vector<double> const& local_xdot,
LocalAssemblerInterface& local_assembler, const double dxdot_dx,
const double dx_dx, CoupledSolutionsForStaggeredScheme const* cpl_xs)
{
std::vector<std::reference_wrapper<const std::vector<GlobalIndexType>>>
indices_of_all_coupled_processes;
indices_of_all_coupled_processes.reserve(cpl_xs->coupled_xs.size());
for (std::size_t i = 0; i < cpl_xs->coupled_xs.size() - 1; i++)
{
indices_of_all_coupled_processes.emplace_back(std::ref(base_indices));
}
indices_of_all_coupled_processes.emplace_back(std::ref(full_indices));
auto local_coupled_xs0 =
getPreviousLocalSolutions(*cpl_xs, indices_of_all_coupled_processes);
auto local_coupled_xs =
getCurrentLocalSolutions(*cpl_xs, indices_of_all_coupled_processes);
ProcessLib::LocalCoupledSolutions local_coupled_solutions(
cpl_xs->dt, cpl_xs->process_id, std::move(local_coupled_xs0),
std::move(local_coupled_xs));
_jacobian_assembler->assembleWithJacobianForStaggeredScheme(
local_assembler, t, local_xdot, dxdot_dx, dx_dx, _local_M_data,
_local_K_data, _local_b_data, _local_Jac_data, local_coupled_solutions);
}
} // namespace ProcessLib