cmake_minimum_required(VERSION 3.28)
project(MeanField CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_compile_options(
        -gdwarf-4
        -Wno-unused-parameter
        -Wno-unused-function
        -Wno-unused-variable
        -Wno-unused-const-variable
        -Wno-unused-private-field
        -Wno-unused-but-set-variable
        -Wno-unused-local-typedefs
        -Wno-unused-value
        -Wno-unused-label
        -Wno-unused-lambda-capture
)

find_package(MPI REQUIRED COMPONENTS CXX)

find_package(XAD REQUIRED)

find_package(mfem REQUIRED)
find_package(UMFPACK REQUIRED)
find_package(hypre REQUIRED)

find_package(PkgConfig REQUIRED)


pkg_check_modules(stroid REQUIRED IMPORTED_TARGET stroid)

add_library(mean_field)

target_include_directories(mean_field
        PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/libmeanfield/include>
)

target_sources(mean_field
        PRIVATE
        libmeanfield/impl/analysis/integral.cpp
        libmeanfield/impl/fem.cpp
        libmeanfield/impl/mapping/coefficients.cpp
        libmeanfield/impl/mapping/domain_mapper.cpp
        libmeanfield/impl/mapping/compactification/kelvin.cpp
        libmeanfield/impl/physics/gravity.cpp
        libmeanfield/impl/physics/solid.cpp
        libmeanfield/impl/utils/domain.cpp
        libmeanfield/impl/utils/misc.cpp
        libmeanfield/impl/integrators/advection.cpp
        libmeanfield/impl/integrators/centrifugal.cpp
        libmeanfield/impl/integrators/coriolis.cpp
        libmeanfield/impl/integrators/gravity.cpp
        libmeanfield/impl/integrators/mass_continuity.cpp
        libmeanfield/impl/integrators/viscosity.cpp
        libmeanfield/impl/mapping/domain_mapper_new.cpp
        libmeanfield/impl/mapping/transformations.cpp
        libmeanfield/impl/operators/gravity_field.cpp
        libmeanfield/impl/operators/gravity_field_jacobian.cpp
        libmeanfield/impl/operators/kernels/gravity_kernels.cpp
        libmeanfield/impl/operators/prepared_hdiv_mass.cpp
        libmeanfield/impl/operators/prepared_gravity_source.cpp
        libmeanfield/impl/operators/contexts/gravity_field_context.cpp
        libmeanfield/impl/operators/kernels/barotropic_closure_kernels.cpp
        libmeanfield/impl/operators/prepared_barotropic_closure.cpp
        libmeanfield/impl/operators/contexts/barotropic_closure_linearization_context.cpp
        libmeanfield/impl/operators/kernels/hydrostatic_equilibrium_kernels.cpp
        libmeanfield/impl/operators/contexts/hydrostatic_equilibrium_context.cpp
        libmeanfield/impl/operators/prepared_hydrostatic_equilibrium.cpp
        libmeanfield/impl/operators/kernels/pressure_force_kernels.cpp
)

target_sources(mean_field
        PUBLIC
        FILE_SET CXX_MODULES FILES
        libmeanfield/interface/mean_field.cppm
        libmeanfield/interface/fem.cppm
        libmeanfield/interface/analysis/integral.cppm
        libmeanfield/interface/boundary/context.cppm
        libmeanfield/interface/mapping/coefficients.cppm
        libmeanfield/interface/mapping/domain_mapper.cppm
        libmeanfield/interface/mapping/types.cppm
        libmeanfield/interface/mapping/transformations.cppm
        libmeanfield/interface/mapping/compactification/compactification.cppm
        libmeanfield/interface/mapping/compactification/kelvin.cppm
        libmeanfield/interface/mapping/compactification/options.cppm
        libmeanfield/interface/physics/context.cppm
        libmeanfield/interface/physics/gravity.cppm
        libmeanfield/interface/physics/solid.cppm
        libmeanfield/interface/utils/domain.cppm
        libmeanfield/interface/utils/misc.cppm
        libmeanfield/interface/utils/user.cppm
        libmeanfield/interface/integrators/advection.cppm
        libmeanfield/interface/integrators/centrifugal.cppm
        libmeanfield/interface/integrators/coriolis.cppm
        libmeanfield/interface/integrators/gravity.cppm
        libmeanfield/interface/integrators/mass_continuity.cppm
        libmeanfield/interface/integrators/pressure_gradient.cppm
        libmeanfield/interface/integrators/viscosity.cppm
        libmeanfield/interface/quadrature/policy.cppm
        libmeanfield/interface/quadrature/mfem.cppm
        libmeanfield/interface/solver/fields.cppm
        libmeanfield/interface/operators/gravity_field.cppm
        libmeanfield/interface/operators/gravity_field_jacobian.cppm
        libmeanfield/interface/operators/kernels/gravity_kernels.cppm
        libmeanfield/interface/operators/kernels/barotropic_closure_kernels.cppm
        libmeanfield/interface/utils/blocks.cppm
        libmeanfield/interface/operators/contexts/gravity_field_context.cppm
        libmeanfield/interface/operators/prepared_gravity_source.cppm
        libmeanfield/interface/operators/prepared_hdiv_mass.cppm
        libmeanfield/interface/operators/prepared_hydrostatic_equilibrium_operator.cppm
        libmeanfield/interface/field/field_base.cppm
        libmeanfield/interface/field/field_registry.cppm
        libmeanfield/interface/field/field_mfem.cppm
        libmeanfield/interface/physics/barotrope.cppm
        libmeanfield/interface/operators/prepared_barotropic_closure_operator.cppm
        libmeanfield/interface/operators/contexts/barotropic_closure_linearization_context.cppm
        libmeanfield/interface/physics/rigid_rotation.cppm
        libmeanfield/interface/operators/kernels/hydrostatic_equilibrium_kernels.cppm
        libmeanfield/interface/operators/contexts/hydrostatic_equilibrium_context.cppm
        libmeanfield/interface/operators/kernels/pressure_force_kernels.cppm
)


target_link_libraries(mean_field
        PUBLIC
        MPI::MPI_CXX
        XAD::xad
        mfem
        PkgConfig::stroid
)

add_library(test_mod)
target_sources(test_mod
        PUBLIC
        FILE_SET CXX_MODULES FILES
        tests/test_helpers.cppm
)
target_link_libraries(test_mod
        PUBLIC
        mean_field
)

find_package(Catch2 3 REQUIRED)

cmake_policy(SET CMP0167 NEW)
find_package(Boost REQUIRED)

pkg_check_modules(fourdst_config REQUIRED IMPORTED_TARGET fourdst_config)

add_executable(tests
        tests/test_main.cpp
        tests/physics/gravity.cpp
        tests/geometry/volume.cpp
        tests/quadrature/policy.cpp
        tests/integrators/centrifugal.cpp
        tests/integrators/gravity.cpp
        tests/mapping/domain_mapper.cpp
        tests/mapping/compactification/kelvin.cpp
        tests/utils/blocks.cpp
        tests/operators/gravity_field.cpp
        tests/mapping/hdiv_mass_tensor.cpp
        tests/operators/prepared_hdiv_mass.cpp
        tests/operators/prepared_gravity_source.cpp
        tests/operators/contexts/gravity_field_context.cpp
        tests/physics/gravity_monopole_accuracy.cpp
        tests/physics/barotrope.cpp
        tests/operators/kernels/barotropic_closure_kernels.cpp
        tests/operators/prepared_barotropic_closure.cpp
        tests/operators/contexts/barotropic_closure_linearization_context.cpp
        tests/operators/kernels/hydrostatic_equilibrium_kernels.cpp
        tests/operators/contexts/hydrostatic_equilibrium_context.cpp
        tests/operators/prepared_hydrostatic_equilibrium.cpp
        tests/operators/prepared_hydrostatic_equilibrium_jacobian.cpp
        tests/operators/prepared_hydrostatic_equilibrium_displacement_jacobian.cpp
        tests/operators/prepared_hydrostatic_equilibrium_complete_jacobian.cpp
        tests/operators/prepared_hydrostatic_equilibrium_analytic_accuracy.cpp
        tests/physics/barotrope_pressure.cpp
        tests/operators/kernels/pressure_force_kernels.cpp

)

target_link_libraries(tests PRIVATE mean_field test_mod Catch2::Catch2 Boost::boost)

add_library(experiment_mod)
target_sources(experiment_mod
        PUBLIC
        FILE_SET CXX_MODULES FILES
        experiments/experiment_results.cppm
)
target_link_libraries(experiment_mod
        PUBLIC
        mean_field
        test_mod
)

add_executable(experiments
        experiments/experiment_main.cpp
        experiments/gravity_accuracy_budget.cpp
)

target_link_libraries(experiments PRIVATE mean_field test_mod experiment_mod Catch2::Catch2 Boost::boost)

include (CTest)
include (Catch)
catch_discover_tests(
        tests
        experiments
        WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)