Abstract
Abstract Reservoir simulators are highly complex computer programs and are often treated as “black boxes” that act on standardized input formats. In part, this is due to the closed-source nature of commercial offerings commonly used in industry, but even when the source-code is available, modification of a fully featured simulator can be a daunting task: A reservoir simulation problem, when fully specified, can have a great number of parameters and functional relationships that are tightly coupled together in most implementations. This is an obstacle to workflows that go beyond forecasting and into optimization, parameter fitting and sensitivity analysis where the solution quantity of interest should be paired with gradients taken with respect to forces and parameters. The monolithic design of typical reservoir simulation codes cannot be separated from the technical and mathematical choices made when discretizing the governing equations: The implicitness required to handle pressure changes and strong coupling between different solution variables means that the Jacobian of the governing equations must be implemented with respect to the primary variables: An error-prone process when done manually, and highly time-consuming when considering coupled systems. Automatic differentiation (AD) is a common cure to this problem that can generate Jacobians, but often comes at a severe cost in runtime performance. A more practical issue is that high computational performance for simulation problems relevant to modern geoenergy operations necessitates implementation in a compiled language while optimization and history matching workflows that integrate many data sources are most naturally expressed in high-level scripting languages. We describe the design of JutulDarcy, an open-source porous media simulator written in the Julia language. JutulDarcy is designed from the ground up with extensibility and computation of sensitivities in mind, starting from the assumption that high-performance automatic differentiation enables us to radically rethink the way simulators are designed. Highlights of this design include arbitrary execution graphs for the equation terms, in which dependence relationships can be re-configured on the fly, easy coupling of models, computation of sensitivities with respect to all model parameters through an adjoint method with a parameter declaration system, and an assembly process with performance that can exceed that of compiled simulators with hand-coded Jacobians. We validate the simulator on a number of standard test cases (immiscible, black-oil, CO2 and compositional flow) and demonstrate MPI parallel performance on multi-million cell models. In addition, we offer a frank assessment of the relative strengths and weaknesses of the Julia programming language for scientific computing.