/*********************************************************************************** OpenCS Project: www.daetools.com Copyright (C) Dragan Nikolic ************************************************************************************ OpenCS is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation. OpenCS 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the OpenCS software; if not, see <http://www.gnu.org/licenses/>. ***********************************************************************************/ #include <mpi.h> #include "brusselator_2d.h" #include <OpenCS/opencs.h> #include <OpenCS/models/partitioner_metis.h> using namespace cs; /* Reimplementation of IDAS idasBruss_kry_bbd_p example. * The PDE system is a two-species time-dependent PDE known as * Brusselator PDE and models a chemically reacting system: * * du/dt = eps1(d2u/dx2 + d2u/dy2) + u^2 v - (B+1)u + A * dv/dt = eps2(d2v/dx2 + d2v/dy2) - u^2 v + Bu * * BC: Homogenous Neumann * IC: u(x,y,t0) = u0(x,y) = 1 - 0.5*cos(pi*y/L) * v(x,y,t0) = v0(x,y) = 3.5 - 2.5*cos(pi*x/L) * * The PDEs are discretized by central differencing on a uniform (Nx, Ny) grid. * The original results are in dae_example_3.csv file. * * The model is described in: * - R. Serban and A. C. Hindmarsh. CVODES, the sensitivity-enabled ODE solver in SUNDIALS. * In Proceedings of the 5th International Conference on Multibody Systems, * Nonlinear Dynamics and Control, Long Beach, CA, 2005. ASME. * - M. R. Wittman. Testing of PVODE, a Parallel ODE Solver. * Technical Report UCRL-ID-125562, LLNL, August 1996. */ int main(int argc, char *argv[]) { uint32_t Nx = 80; uint32_t Ny = 80; if(argc == 3) { Nx = atoi(argv[1]); Ny = atoi(argv[2]); } else if(argc == 1) { // Use the default grid size. } else { printf("Usage:\n"); printf(" %s (using the default grid: %u x %u)\n", argv[0], Nx, Ny); printf(" %s Nx Ny\n", argv[0]); return -1; } printf("########################################################\n"); printf(" Brusselator model in 2D: %u x %u grid\n", Nx, Ny); printf("########################################################\n"); // Homogenous Neumann BCs at all four edges. csNumber_t bc_u_flux(0.0); csNumber_t bc_v_flux(0.0); Brusselator_2D bruss(Nx, Ny, bc_u_flux, bc_v_flux); uint32_t Ndofs = 0; uint32_t Nvariables = bruss.Nequations; real_t defaultVariableValue = 0.0; real_t defaultVariableTimeDerivative = 0.0; real_t defaultAbsoluteTolerance = 1e-5; std::string defaultVariableName = "x"; /* 1. Initialise model builder with the number of variables/equations. */ csModelBuilder_t mb; mb.Initialize_DAE_System(Nvariables, Ndofs, defaultVariableValue, defaultVariableTimeDerivative, defaultAbsoluteTolerance, defaultVariableName); printf("Model builder initialised\n"); /* 2. Create and set model equations. */ const std::vector<csNumber_t>& x_vars = mb.GetVariables(); const std::vector<csNumber_t>& xt_vars = mb.GetTimeDerivatives(); std::vector<csNumber_t> equations(Nvariables); bruss.CreateEquations(x_vars, xt_vars, equations); printf("Model equations generated\n"); mb.SetModelEquations(equations); printf("Model equations set\n"); // Set variable names std::vector<std::string> names; bruss.GetVariableNames(names); mb.SetVariableNames(names); /* 3. Export model(s) to a specified directory for sequential and parallel simulations. */ // Set initial conditions. std::vector<real_t> uv0(Nvariables, 0.0); bruss.SetInitialConditions(uv0); mb.SetVariableValues(uv0); // Set the simulation options. csSimulationOptionsPtr options = mb.GetSimulationOptions(); options->SetDouble("Simulation.TimeHorizon", 20.0); options->SetDouble("Simulation.ReportingInterval", 0.5); options->SetDouble("Solver.Parameters.RelativeTolerance", 1e-5); // Linear solver //options->SetString ("Model.Evaluators.Device_0.Library", "OpenCL"); //options->SetString ("Model.Evaluators.Device_0.Name", "ocl"); //options->SetInteger("Model.Evaluators.Device_0.Parameters.platformID", 0); //options->SetInteger("Model.Evaluators.Device_0.Parameters.deviceID", 0); options->SetString ("Model.Evaluators.Device_0.Library", "OpenCL_FPGA"); options->SetString ("Model.Evaluators.Device_0.Name", "ocl_fpga"); options->SetInteger("Model.Evaluators.Device_0.Parameters.platformID", 0); options->SetInteger("Model.Evaluators.Device_0.Parameters.deviceID", 0); // For Ncpu = 1: k = 3, rho = 1.0, alpha = 1e-1, w = 0.5 options->SetInteger("LinearSolver.Preconditioner.Parameters.fact: level-of-fill", 3); options->SetDouble ("LinearSolver.Preconditioner.Parameters.fact: relax value", 0.5); options->SetDouble ("LinearSolver.Preconditioner.Parameters.fact: absolute threshold", 1e-1); options->SetDouble ("LinearSolver.Preconditioner.Parameters.fact: relative threshold", 1.0); std::string simulationOptions_seq = options->ToString(); /* Model export requires partitioning of the system and simulation options (in JSON format). * For Npe = 1, graph partitioner is not required (the whole system of equations is used). * For distributed memory systems a graph partitioner must be specified. * Available partitioners: * - Simple * - 2D_Npde (for discretisation of Npde equations on uniform 2D grids) * - Metis: * - PartGraphKway: 'Multilevel k-way partitioning' algorithm * - PartGraphRecursive: 'Multilevel recursive bisectioning' algorithm * Metis partitioner can additionally balance specified quantities in all partitions using the balancing constraints. * Available balancing constraints: * - Ncs: balance number of compute stack items in equations * - Nnz: balance number of non-zero items in the incidence matrix * - Nflops: balance number of FLOPS required to evaluate equations * - Nflops_j: balance number of FLOPS required to evaluate derivatives (Jacobian) matrix */ // Generate a single model (no graph partitioner required). std::string inputFilesDirectory = "dae_example_3-fpga-sequential"; inputFilesDirectory += "-" + std::to_string(Nx) + "x" + std::to_string(Ny); { uint32_t Npe = 1; std::vector<std::string> balancingConstraints; csGraphPartitioner_t* gp = NULL; std::vector<csModelPtr> models_sequential = mb.PartitionSystem(Npe, gp, balancingConstraints, true); csModelBuilder_t::ExportModels(models_sequential, inputFilesDirectory, simulationOptions_seq); printf("Generated %s model for Npe = 1\n", inputFilesDirectory.c_str()); } /* 4. Simulate the sequential model using the libOpenCS_Simulators. */ printf("Simulation of '%s' (using libOpenCS_Simulators)\n\n", inputFilesDirectory.c_str()); MPI_Init(&argc, &argv); csSimulate(inputFilesDirectory); MPI_Finalize(); return 0; }