Пример #1
0
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);
}
Пример #2
0
void VectorMatrixAssembler::assemble(
    const std::size_t mesh_item_id, LocalAssemblerInterface& local_assembler,
    std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>> const&
        dof_tables,
    const double t, const GlobalVector& x, GlobalMatrix& M, GlobalMatrix& K,
    GlobalVector& b, CoupledSolutionsForStaggeredScheme const* const cpl_xs)
{
    std::vector<std::vector<GlobalIndexType>> indices_of_processes;
    indices_of_processes.reserve(dof_tables.size());
    for (std::size_t i = 0; i < dof_tables.size(); i++)
    {
        indices_of_processes.emplace_back(
            NumLib::getIndices(mesh_item_id, dof_tables[i].get()));
    }

    auto const& indices = (cpl_xs == nullptr)
                              ? indices_of_processes[0]
                              : indices_of_processes[cpl_xs->process_id];
    _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
    {
        auto local_coupled_xs0 =
            getPreviousLocalSolutions(*cpl_xs, indices_of_processes);
        auto local_coupled_xs =
            getCurrentLocalSolutions(*cpl_xs, indices_of_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);
    }
}
Пример #3
0
void CentralDifferencesJacobianAssembler::assembleWithJacobian(
    LocalAssemblerInterface& local_assembler, const double t,
    const std::vector<double>& local_x_data,
    const std::vector<double>& local_xdot_data, const double dxdot_dx,
    const double dx_dx, std::vector<double>& local_M_data,
    std::vector<double>& local_K_data, std::vector<double>& local_b_data,
    std::vector<double>& local_Jac_data)
{
    // TODO do not check in every call.
    if (local_x_data.size() % _absolute_epsilons.size() != 0) {
        OGS_FATAL(
            "The number of specified epsilons (%u) and the number of local "
            "d.o.f.s (%u) do not match, i.e., the latter is not divisable by "
            "the former.",
            _absolute_epsilons.size(), local_x_data.size());
    }

    auto const num_r_c =
        static_cast<Eigen::MatrixXd::Index>(local_x_data.size());

    auto const local_x =
        MathLib::toVector<Eigen::VectorXd>(local_x_data, num_r_c);
    auto const local_xdot =
        MathLib::toVector<Eigen::VectorXd>(local_xdot_data, num_r_c);

    auto local_Jac = MathLib::createZeroedMatrix(local_Jac_data,
                                             num_r_c, num_r_c);
    _local_x_perturbed_data = local_x_data;

    auto const num_dofs_per_component =
        local_x_data.size() / _absolute_epsilons.size();

    // Residual  res := M xdot + K x - b
    // Computing Jac := dres/dx
    //                = M dxdot/dx + dM/dx xdot + K dx/dx + dK/dx x - db/dx
    //                  (Note: dM/dx and dK/dx actually have the second and
    //                  third index transposed.)
    // The loop computes the dM/dx, dK/dx and db/dx terms, the rest is computed
    // afterwards.
    for (Eigen::MatrixXd::Index i = 0; i < num_r_c; ++i)
    {
        // assume that local_x_data is ordered by component.
        auto const component = i / num_dofs_per_component;
        auto const eps = _absolute_epsilons[component];

        _local_x_perturbed_data[i] += eps;
        local_assembler.assemble(t, _local_x_perturbed_data, local_M_data,
                                 local_K_data, local_b_data);

        _local_x_perturbed_data[i] = local_x_data[i] - eps;
        local_assembler.assemble(t, _local_x_perturbed_data, _local_M_data,
                                 _local_K_data, _local_b_data);

        _local_x_perturbed_data[i] = local_x_data[i];

        if (!local_M_data.empty()) {
            auto const local_M_p =
                MathLib::toMatrix(local_M_data, num_r_c, num_r_c);
            auto const local_M_m =
                MathLib::toMatrix(_local_M_data, num_r_c, num_r_c);
            local_Jac.col(i).noalias() +=
                // dM/dxi * x_dot
                (local_M_p - local_M_m) * local_xdot / (2.0 * eps);
            local_M_data.clear();
            _local_M_data.clear();
        }
        if (!local_K_data.empty()) {
            auto const local_K_p =
                MathLib::toMatrix(local_K_data, num_r_c, num_r_c);
            auto const local_K_m =
                MathLib::toMatrix(_local_K_data, num_r_c, num_r_c);
            local_Jac.col(i).noalias() +=
                // dK/dxi * x
                (local_K_p - local_K_m) * local_x / (2.0 * eps);
            local_K_data.clear();
            _local_K_data.clear();
        }
        if (!local_b_data.empty()) {
            auto const local_b_p =
                MathLib::toVector<Eigen::VectorXd>(local_b_data, num_r_c);
            auto const local_b_m =
                MathLib::toVector<Eigen::VectorXd>(_local_b_data, num_r_c);
            local_Jac.col(i).noalias() -=
                // db/dxi
                (local_b_p - local_b_m) / (2.0 * eps);
            local_b_data.clear();
            _local_b_data.clear();
        }
    }

    // Assemble with unperturbed local x.
    local_assembler.assemble(t, local_x_data, local_M_data, local_K_data,
                             local_b_data);

    // Compute remaining terms of the Jacobian.
    if (dxdot_dx != 0.0 && !local_M_data.empty()) {
        auto local_M = MathLib::toMatrix(local_M_data, num_r_c, num_r_c);
        local_Jac.noalias() += local_M * dxdot_dx;
    }
    if (dx_dx != 0.0 && !local_K_data.empty()) {
        auto local_K = MathLib::toMatrix(local_K_data, num_r_c, num_r_c);
        local_Jac.noalias() += local_K * dx_dx;
    }
}