TpfaCompressibleAssembler.hpp
Go to the documentation of this file.
1/*
2 Copyright 2010 SINTEF ICT, Applied Mathematics.
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef OPM_TPFACOMPRESSIBLEASSEMBLER_HEADER_INCLUDED
21#define OPM_TPFACOMPRESSIBLEASSEMBLER_HEADER_INCLUDED
22
23
24#include <opm/core/pressure/tpfa/cfs_tpfa.h>
25#include <opm/core/pressure/tpfa/trans_tpfa.h>
26#include <opm/core/linalg/sparse_sys.h>
27#include <opm/core/pressure/flow_bc.h>
28#include <opm/core/pressure/legacy_well.h>
29#include <opm/core/pressure/tpfa/compr_quant.h>
30#include <dune/grid/common/GridAdapter.hpp>
31#include <stdexcept>
32
33
34
39{
40public:
44 : state_(Uninitialized), data_(0), bc_(0)
45 {
46 wells_.number_of_wells = 0;
47 }
48
49
50
51
55 {
56 flow_conditions_destroy(bc_);
57 cfs_tpfa_destroy(data_);
58 }
59
60
61
62
72 template <class Grid, class Wells>
73 void init(const Grid& grid, const Wells& wells, const double* perm, const double* porosity,
74 const typename Grid::Vector& gravity)
75 {
76 initWells(wells);
77 init(grid, perm, porosity, gravity);
78 }
79
86 template <class Grid>
87 void init(const Grid& grid, const double* perm, const double* porosity, const typename Grid::Vector& gravity)
88 {
89 // Build C grid structure.
90 grid_.init(grid);
91
92 // Initialize data.
93 int num_phases = 3;
94 well_t* w = 0;
95 if (wells_.number_of_wells != 0) {
96 w = &wells_;
97 }
98 data_ = cfs_tpfa_construct(grid_.c_grid(), w, num_phases);
99 if (!data_) {
100 throw std::runtime_error("Failed to initialize cfs_tpfa solver.");
101 }
102
103 // Compute half-transmissibilities
104 int num_cells = grid.numCells();
105 int ngconn = grid_.c_grid()->cell_facepos[num_cells];
106 ncf_.resize(num_cells);
107 for (int cell = 0; cell < num_cells; ++cell) {
108 int num_local_faces = grid.numCellFaces(cell);
109 ncf_[cell] = num_local_faces;
110 }
111 htrans_.resize(ngconn);
112 tpfa_htrans_compute(grid_.c_grid(), perm, &htrans_[0]);
113
114 // Compute transmissibilities.
115 trans_.resize(grid_.numFaces());
116 tpfa_trans_compute(grid_.c_grid(), &htrans_[0], &trans_[0]);
117
118 // Compute pore volumes.
119 porevol_.resize(num_cells);
120 for (int i = 0; i < num_cells; ++i) {
121 porevol_[i] = porosity[i]*grid.cellVolume(i);
122 }
123
124 // Set gravity.
125 if (Grid::dimension != 3) {
126 throw std::logic_error("Only 3 dimensions supported currently.");
127 }
128 std::copy(gravity.begin(), gravity.end(), gravity_);
129
130 state_ = Initialized;
131 }
132
133
134
136 enum FlowBCTypes { FBC_UNSET = BC_NOFLOW ,
137 FBC_PRESSURE = BC_PRESSURE ,
138 FBC_FLUX = BC_FLUX_TOTVOL };
139
151 void assemble(const double* sources,
152 const FlowBCTypes* bctypes,
153 const double* bcvalues,
154 const double dt,
155 const double* totcompr,
156 const double* voldiscr,
157 const double* cellA, // num phases^2 * num cells, fortran ordering!
158 const double* faceA, // num phases^2 * num faces, fortran ordering!
159 const double* wellperfA,
160 const double* phasemobf,
161 const double* phasemobwellperf,
162 const double* cell_pressure,
163 const double* gravcapf,
164 const double* wellperf_gpot,
165 const double* surf_dens)
166 {
167 if (state_ == Uninitialized) {
168 throw std::runtime_error("Error in TpfaCompressibleAssembler::assemble(): You must call init() prior to calling assemble().");
169 }
170 UnstructuredGrid* g = grid_.c_grid();
171
172 // Boundary conditions.
173 gather_boundary_conditions(bctypes, bcvalues);
174
175 // Source terms from user.
176 double* src = const_cast<double*>(sources); // Ugly? Yes. Safe? I think so.
177
178 // Wells.
179 well_t* wells = NULL;
180 well_control_t* wctrl = NULL;
181 struct completion_data* wcompl = NULL;
182 if (wells_.number_of_wells != 0) {
183 wells = &wells_;
184 wctrl = &wctrl_;
185 wcompl = &wcompl_;
186 // The next objects already have the correct sizes.
187 std::copy(wellperf_gpot, wellperf_gpot + well_gpot_storage_.size(), well_gpot_storage_.begin());
188 std::copy(wellperfA, wellperfA + well_A_storage_.size(), well_A_storage_.begin());
189 std::copy(phasemobwellperf, phasemobwellperf + well_phasemob_storage_.size(), well_phasemob_storage_.begin());
190 }
191
192 // Assemble the embedded linear system.
193 compr_quantities cq = { 3 ,
194 const_cast<double *>(totcompr ) ,
195 const_cast<double *>(voldiscr ) ,
196 const_cast<double *>(cellA ) ,
197 const_cast<double *>(faceA ) ,
198 const_cast<double *>(phasemobf) };
199
200 // Call the assembly routine. After this, linearSystem() may be called.
201 cfs_tpfa_assemble(g, dt, wells, bc_, src,
202 &cq, &trans_[0], gravcapf,
203 wctrl, wcompl,
204 cell_pressure, &porevol_[0],
205 data_);
206 phasemobf_.assign(phasemobf, phasemobf + grid_.numFaces()*3);
207 gravcapf_.assign(gravcapf, gravcapf + grid_.numFaces()*3);
208 state_ = Assembled;
209 }
210
211
212
213
216 {
217 int n;
218 int nnz;
219 int* ia;
220 int* ja;
221 double* sa;
222 double* b;
223 double* x;
224 };
225
233
234 {
235 if (state_ != Assembled) {
236 throw std::runtime_error("Error in TpfaCompressibleAssembler::linearSystem(): "
237 "You must call assemble() prior to calling linearSystem().");
238 }
239 s.n = data_->A->m;
240 s.nnz = data_->A->nnz;
241 s.ia = data_->A->ia;
242 s.ja = data_->A->ja;
243 s.sa = data_->A->sa;
244 s.b = data_->b;
245 s.x = data_->x;
246 }
247
248
249
250
258 void computePressuresAndFluxes(std::vector<double>& cell_pressures,
259 std::vector<double>& face_pressures,
260 std::vector<double>& face_fluxes,
261 std::vector<double>& well_pressures,
262 std::vector<double>& well_fluxes)
263 {
264 if (state_ != Assembled) {
265 throw std::runtime_error("Error in TpfaCompressibleAssembler::computePressuresAndFluxes(): "
266 "You must call assemble() (and solve the linear system) "
267 "prior to calling computePressuresAndFluxes().");
268 }
269 int num_cells = grid_.c_grid()->number_of_cells;
270 int num_faces = grid_.c_grid()->number_of_faces;
271 cell_pressures.clear();
272 cell_pressures.resize(num_cells, 0.0);
273 face_pressures.clear();
274 face_pressures.resize(num_faces, 0.0);
275 face_fluxes.clear();
276 face_fluxes.resize(num_faces, 0.0);
277
278 int np = 3; // Number of phases.
279
280 // Wells.
281 well_t* wells = NULL;
282 struct completion_data* wcompl = NULL;
283 double* wpress = 0;
284 double* wflux = 0;
285 if (wells_.number_of_wells != 0) {
286 wells = &wells_;
287 wcompl = &wcompl_;
288 well_pressures.resize(wells_.number_of_wells);
289 well_fluxes.resize(well_cells_storage_.size());
290 wpress = &well_pressures[0];
291 wflux = &well_fluxes[0];
292 }
293
294 cfs_tpfa_press_flux(grid_.c_grid(),
295 bc_, wells,
296 np, &trans_[0], &phasemobf_[0], &gravcapf_[0],
297 wcompl,
298 data_, &cell_pressures[0], &face_fluxes[0],
299 wpress, wflux);
300 cfs_tpfa_fpress(grid_.c_grid(), bc_, np, &htrans_[0],
301 &phasemobf_[0], &gravcapf_[0], data_, &cell_pressures[0],
302 &face_fluxes[0], &face_pressures[0]);
303 }
304
305
306
307
310 double explicitTimestepLimit(const double* faceA, // num phases^2 * num faces, fortran ordering!
311 const double* phasemobf,
312 const double* phasemobf_deriv,
313 const double* surf_dens)
314 {
315 compr_quantities cq = { 3, // nphases
316 0, // totcompr
317 0, // voldiscr
318 0, // Ac
319 const_cast<double *>(faceA) ,
320 const_cast<double *>(phasemobf) };
321 return cfs_tpfa_impes_maxtime(grid_.c_grid(), &cq, &trans_[0], &porevol_[0], data_,
322 phasemobf_deriv, surf_dens, gravity_);
323 }
324
325
326
329 void explicitTransport(const double dt,
330 double* cell_surfvols)
331 {
332 int np = 3; // Number of phases.
333
334 well_t* wells = NULL;
335 if (wells_.number_of_wells != 0) {
336 wells = &wells_;
337 }
338 cfs_tpfa_expl_mass_transport(grid_.c_grid(), wells, &wcompl_,
339 np, dt, &porevol_[0],
340 data_, cell_surfvols);
341 }
342
343
344
345
358 void faceFluxToCellFlux(const std::vector<double>& face_fluxes,
359 std::vector<double>& cell_fluxes)
360 {
361 if (state_ != Assembled) {
362 throw std::runtime_error("Error in TpfaCompressibleAssembler::faceFluxToCellFlux(): "
363 "You must call assemble() (and solve the linear system) "
364 "prior to calling faceFluxToCellFlux().");
365 }
366 const UnstructuredGrid& g = *(grid_.c_grid());
367 int num_cells = g.number_of_cells;
368 cell_fluxes.resize(g.cell_facepos[num_cells]);
369 for (int cell = 0; cell < num_cells; ++cell) {
370 for (int hface = g.cell_facepos[cell]; hface < g.cell_facepos[cell + 1]; ++hface) {
371 int face = g.cell_faces[hface];
372 bool pos = (g.face_cells[2*face] == cell);
373 cell_fluxes[hface] = pos ? face_fluxes[face] : -face_fluxes[face];
374 }
375 }
376 }
377
378
379
380
383 const std::vector<int>& numCellFaces() const
384 {
385 return ncf_;
386 }
387
388
389 const std::vector<double>& faceTransmissibilities() const
390 {
391 return trans_;
392 }
393
394private:
395 // Disabling copy and assigment for now.
398
399 enum State { Uninitialized, Initialized, Assembled };
400 State state_;
401
402 // Solver data.
403 cfs_tpfa_data* data_;
404 // Grid.
405 GridAdapter grid_;
406 // Number of faces per cell.
407 std::vector<int> ncf_;
408 // Transmissibility storage.
409 std::vector<double> htrans_;
410 std::vector<double> trans_;
411 // Pore volumes.
412 std::vector<double> porevol_;
413 // Phase mobilities per face.
414 std::vector<double> phasemobf_;
415 // Gravity and capillary contributions (per face).
416 std::vector<double> gravcapf_;
417 // Gravity
418 double gravity_[3];
419
420 // Boundary conditions.
421 FlowBoundaryConditions *bc_;
422
423 // Well data
424 well_t wells_;
425 std::vector<int> well_connpos_storage_;
426 std::vector<int> well_cells_storage_;
427 well_control_t wctrl_;
428 std::vector<well_type> wctrl_type_storage_;
429 std::vector<well_control> wctrl_ctrl_storage_;
430 std::vector<double> wctrl_target_storage_;
431 struct completion_data wcompl_;
432 std::vector<double> well_prodind_storage_;
433 std::vector<double> well_gpot_storage_;
434 std::vector<double> well_A_storage_;
435 std::vector<double> well_phasemob_storage_;
436
437
444 template <class Wells>
445 void initWells(const Wells& w)
446 {
447 int num_wells = w.numWells();
448 if (num_wells == 0) {
449 wells_.number_of_wells = 0;
450 return;
451 }
452 wctrl_type_storage_.resize(num_wells);
453 wctrl_ctrl_storage_.resize(num_wells);
454 wctrl_target_storage_.resize(num_wells);
455 for (int i = 0; i < num_wells; ++i) {
456 wctrl_type_storage_[i] = (w.type(i) == Wells::Injector) ? INJECTOR : PRODUCER;
457 wctrl_ctrl_storage_[i] = (w.control(i) == Wells::Rate) ? RATE : BHP;
458 wctrl_target_storage_[i] = w.target(i);
459 int num_perf = w.numPerforations(i);
460 well_connpos_storage_.push_back(well_cells_storage_.size());
461 for (int j = 0; j < num_perf; ++j) {
462 well_cells_storage_.push_back(w.wellCell(i, j));
463 well_prodind_storage_.push_back(w.wellIndex(i, j));
464 }
465 }
466 well_connpos_storage_.push_back(well_cells_storage_.size());
467 int tot_num_perf = well_prodind_storage_.size();
468 well_gpot_storage_.resize(tot_num_perf*3);
469 well_A_storage_.resize(3*3*tot_num_perf);
470 well_phasemob_storage_.resize(3*tot_num_perf);
471 // Setup 'wells_'
472 wells_.number_of_wells = num_wells;
473 wells_.well_connpos = &well_connpos_storage_[0];
474 wells_.well_cells = &well_cells_storage_[0];
475 // Setup 'wctrl_'
476 wctrl_.type = &wctrl_type_storage_[0];
477 wctrl_.ctrl = &wctrl_ctrl_storage_[0];
478 wctrl_.target = &wctrl_target_storage_[0];
479 // Setup 'wcompl_'
480 wcompl_.WI = &well_prodind_storage_[0];
481 wcompl_.gpot = &well_gpot_storage_[0];
482 wcompl_.A = &well_A_storage_[0];
483 wcompl_.phasemob = &well_phasemob_storage_[0];
484 }
485
486
487 void
488 gather_boundary_conditions(const FlowBCTypes* bctypes ,
489 const double* bcvalues)
490 {
491 if (bc_ == 0) {
492 bc_ = flow_conditions_construct(0);
493 }
494 else {
495 flow_conditions_clear(bc_);
496 }
497
498 int ok = bc_ != 0;
499
500 for (std::size_t i = 0, nf = grid_.numFaces(); ok && (i < nf); ++i) {
501 if (bctypes[ i ] == FBC_PRESSURE) {
502 ok = flow_conditions_append(BC_PRESSURE,
503 static_cast<int>(i),
504 bcvalues[ i ],
505 bc_);
506 }
507 else if (bctypes[ i ] == FBC_FLUX) {
508 ok = flow_conditions_append(BC_FLUX_TOTVOL,
509 static_cast<int>(i),
510 bcvalues[ i ],
511 bc_);
512 }
513 }
514
515 if (! ok) {
516 flow_conditions_destroy(bc_);
517 bc_ = 0;
518 }
519 }
520
521
522}; // class TpfaCompressibleAssembler
523
524
525
526
527#endif // OPM_TPFACOMPRESSIBLEASSEMBLER_HEADER_INCLUDED
Encapsulates the cfs_tpfa (= compressible flow solver two-point flux approximation) solver modules.
Definition: TpfaCompressibleAssembler.hpp:39
void init(const Grid &grid, const double *perm, const double *porosity, const typename Grid::Vector &gravity)
Initialize the solver's structures for a given grid, for well setup also call initWells().
Definition: TpfaCompressibleAssembler.hpp:87
const std::vector< int > & numCellFaces() const
Access the number of connections (faces) per cell. Deprecated, will be removed.
Definition: TpfaCompressibleAssembler.hpp:383
void linearSystem(LinearSystem &s)
Access the linear system assembled. You must call assemble() prior to calling linearSystem().
Definition: TpfaCompressibleAssembler.hpp:232
void init(const Grid &grid, const Wells &wells, const double *perm, const double *porosity, const typename Grid::Vector &gravity)
Initialize the solver's structures for a given grid, for well setup also call initWells().
Definition: TpfaCompressibleAssembler.hpp:73
void computePressuresAndFluxes(std::vector< double > &cell_pressures, std::vector< double > &face_pressures, std::vector< double > &face_fluxes, std::vector< double > &well_pressures, std::vector< double > &well_fluxes)
Compute cell pressures and face fluxes. You must call assemble() (and solve the linear system accesse...
Definition: TpfaCompressibleAssembler.hpp:258
~TpfaCompressibleAssembler()
Destructor.
Definition: TpfaCompressibleAssembler.hpp:54
FlowBCTypes
Boundary condition types.
Definition: TpfaCompressibleAssembler.hpp:136
@ FBC_FLUX
Definition: TpfaCompressibleAssembler.hpp:138
@ FBC_PRESSURE
Definition: TpfaCompressibleAssembler.hpp:137
@ FBC_UNSET
Definition: TpfaCompressibleAssembler.hpp:136
double explicitTimestepLimit(const double *faceA, const double *phasemobf, const double *phasemobf_deriv, const double *surf_dens)
Explicit IMPES time step limit.
Definition: TpfaCompressibleAssembler.hpp:310
TpfaCompressibleAssembler()
Default constructor, does nothing.
Definition: TpfaCompressibleAssembler.hpp:43
void explicitTransport(const double dt, double *cell_surfvols)
Explicit IMPES transport.
Definition: TpfaCompressibleAssembler.hpp:329
void faceFluxToCellFlux(const std::vector< double > &face_fluxes, std::vector< double > &cell_fluxes)
Compute cell fluxes from face fluxes. You must call assemble() (and solve the linear system accessed ...
Definition: TpfaCompressibleAssembler.hpp:358
void assemble(const double *sources, const FlowBCTypes *bctypes, const double *bcvalues, const double dt, const double *totcompr, const double *voldiscr, const double *cellA, const double *faceA, const double *wellperfA, const double *phasemobf, const double *phasemobwellperf, const double *cell_pressure, const double *gravcapf, const double *wellperf_gpot, const double *surf_dens)
Assemble the sparse system. You must call init() prior to calling assemble().
Definition: TpfaCompressibleAssembler.hpp:151
const std::vector< double > & faceTransmissibilities() const
Definition: TpfaCompressibleAssembler.hpp:389
Encapsulate a sparse linear system in CSR format.
Definition: TpfaCompressibleAssembler.hpp:216
double * sa
Definition: TpfaCompressibleAssembler.hpp:221
double * b
Definition: TpfaCompressibleAssembler.hpp:222
int nnz
Definition: TpfaCompressibleAssembler.hpp:218
int * ja
Definition: TpfaCompressibleAssembler.hpp:220
int * ia
Definition: TpfaCompressibleAssembler.hpp:219
double * x
Definition: TpfaCompressibleAssembler.hpp:223
int n
Definition: TpfaCompressibleAssembler.hpp:217