/* * Relaxation solver for a 2nd order 2D linear PDE. * Copyright 2018 Anton Khirnov * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MG2D_ELL_RELAX_H #define MG2D_ELL_RELAX_H /** * The problem being solved is a linear partial differential * equation * * ∑ C_{ab} ∂_a ∂_b u + ∑ C_{a} ∂_a u + C u = rhs * a,b a * * where * * a and b identify spatial directions and run from 0 to 1 * * u = u(x_a) is the unknown function * * C_{ab}, C_{a} and C are the coefficients in front of * the corresponding derivative of unknown function * * rhs is the right-hand side of the equation * C_{*} and rhs are all (known) functions of space and define the * equation to be solved. */ #include #include #include #include "log.h" #include "mg2d_boundary.h" #include "mg2d_constants.h" typedef struct EllRelaxInternal EllRelaxInternal; typedef struct EllRelaxContext { /** * Solver private data, not to be accessed in any way by the caller. */ EllRelaxInternal *priv; /** * The logging context, to be filled by the caller before mg2di_ell_relax_init(). */ MG2DLogger logger; /** * The thread pool used for execution. May be set by the caller before * mg2di_ell_relax_init(). */ TPContext *tp; /** * Flags indicating supported CPU features. */ int cpuflags; /** * Size of the solver grid, set by mg2di_ell_relax_alloc(). * Read-only for the caller. */ size_t domain_size[2]; /** * Distance between the neighbouring grid points. * Must be set by the caller before mg2di_ell_relax_init(). */ double step[2]; /** * Order of the finite difference operators used for approximating derivatives. * Must be set by the caller before mg2di_ell_relax_init(). */ size_t fd_stencil; /** * Boundary specification, indexed by MG2DBoundaryLoc. * To be filled by the caller before mg2di_ell_relax_init(). */ MG2DBoundary *boundaries[4]; /** * The time stepping factor in relaxation. */ double relax_factor; /** * Values of the unknown function. * * Allocated by the solver in mg2di_ell_relax_alloc(), owned by the solver. * Must be filled by the caller before mg2di_ell_relax_init() to set the * initial guess. * Afterwards updated in mg2di_ell_relax_step(). */ double *u; /** * Distance between neighbouring gridpoints along coord1. */ ptrdiff_t u_stride; /** * Values of the right-hand side. * * Allocated by the solver in mg2di_ell_relax_alloc(), owned by the solver. * Must be filled by the caller before mg2di_ell_relax_init(). */ double *rhs; /** * Distance between neighbouring gridpoints along coord1. */ ptrdiff_t rhs_stride; /** * Values of the right-hand side. * * Allocated by the solver in mg2di_ell_relax_alloc(), owned by the solver. * Read-only for the caller. Initialized after mg2di_ell_relax_init(), * afterwards updated in mg2di_ell_relax_step(). */ double *residual; /** * Distance between neighbouring gridpoints along coord1. */ ptrdiff_t residual_stride; /** * Maximum of the absolute value of residual. */ double residual_max; /** * Coefficients C_{*} that define the differential equation. * * Allocated by the solver in mg2di_ell_relax_alloc(), owned by the solver. * Must be filled by the caller before mg2di_ell_relax_init(). */ double *diff_coeffs[MG2D_DIFF_COEFF_NB]; /** * Distance between neighbouring gridpoints along coord1. */ ptrdiff_t diff_coeffs_stride; /* timings */ int64_t count_correct; int64_t time_correct; int64_t time_boundaries; int64_t count_boundaries; int64_t time_res_calc; int64_t count_res; } EllRelaxContext; /** * Allocate the solver for the given domain size. * * @param domain_size number of grid points in each direction. * * @return The solver context on success, NULL on failure. */ EllRelaxContext *mg2di_ell_relax_alloc(size_t domain_size[2]); /** * Initialize the solver for use, after all the required fields are filled by * the caller. * * This function may be called multiple times to re-initialize the solver after * certain parameters (e.g. the right-hand side or the equation coefficients) * change. * * @return 0 on success, a negative error code on failure. */ int mg2di_ell_relax_init(EllRelaxContext *ctx); /** * Free the solver and write NULL to the provided pointer. */ void mg2di_ell_relax_free(EllRelaxContext **ctx); /** * Perform a single relaxation step. * * @return 0 on success, a negative error code on failure. */ int mg2di_ell_relax_step(EllRelaxContext *ctx); #endif /* MG2D_ELL_RELAX_H */