tpsalinearizer.hpp
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 Copyright 2025 NORCE AS
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20
21 Consult the COPYING file in the top-level source directory of this
22 module for the precise wording of the license and the list of
23 copyright holders.
24*/
25#ifndef TPSA_LINEARIZER_HPP
26#define TPSA_LINEARIZER_HPP
27
28#include <dune/common/fvector.hh>
29
30#include <opm/common/TimingMacros.hpp>
31
32#include <opm/grid/utility/SparseTable.hpp>
33
34#include <opm/input/eclipse/Schedule/BCState.hpp>
35
36#include <opm/material/materialstates/MaterialStateTPSA.hpp>
37
40
41#include <cassert>
42#include <set>
43#include <vector>
44
45
46namespace Opm {
47
51template<class TypeTag>
53{
54 using Constraints = GetPropType<TypeTag, Properties::Constraints>; // TODO: make TPSA constraints
66
67 using MaterialState = MaterialStateTPSA<Evaluation>;
68
69 enum { numEq = getPropValue<TypeTag, Properties::NumEqTPSA>() };
70
71 using ADVectorBlock = Dune::FieldVector<Evaluation, numEq>;
72 using MatrixBlock = typename SparseMatrixAdapter::MatrixBlock;
73 using BlockAddress = typename SparseMatrixAdapter::BlockAddress;
74 using VectorBlock = Dune::FieldVector<Scalar, numEq>;
75
76 using StressInfoVector = Dune::FieldVector<Scalar, 3>;
77
78public:
79 // ///
80 // Public functions
81 // ///
86 {
87 simulatorPtr_ = nullptr;
88 }
89
98 void init(Simulator& simulator)
99 {
100 simulatorPtr_ = &simulator;
101 eraseMatrix();
102 }
103
111 {
112 jacobian_.reset();
113 }
114
118 void finalize()
119 {
120 jacobian_->finalize();
121 }
122
128 template <class SubDomainType>
129 void resetSystem_(const SubDomainType& domain)
130 {
131 if (!jacobian_) {
132 initFirstIteration_();
133 }
134 for (int globI : domain.cells) {
135 residual_[globI] = 0.0;
136 jacobian_->clearRow(globI, 0.0);
137 }
138 }
139
144 {
147 }
148
156 {
157 int succeeded;
158 try {
159 linearizeDomain(fullDomain_);
160 succeeded = 1;
161 }
162 catch (const std::exception& e) {
163 std::cout << "rank " << simulator_().gridView().comm().rank()
164 << " caught an exception while linearizing TPSA system:" << e.what()
165 << "\n" << std::flush;
166 succeeded = 0;
167 }
168 catch (...) {
169 std::cout << "rank " << simulator_().gridView().comm().rank()
170 << " caught an exception while linearizing TPSA system"
171 << "\n" << std::flush;
172 succeeded = 0;
173 }
174 succeeded = simulator_().gridView().comm().min(succeeded);
175
176 if (!succeeded) {
177 throw NumericalProblem("A process did not succeed in linearizing the TPSA system");
178 }
179 }
180
189 template <class SubDomainType>
190 void linearizeDomain(const SubDomainType& domain)
191 {
192 OPM_TIMEBLOCK(linearizeDomain);
193
194 // We defer the initialization of the Jacobian matrix until here because the auxiliary modules usually assume
195 // the problem, model and grid to be fully initialized'
196 if (!jacobian_) {
197 initFirstIteration_();
198 }
199
200 if (domain.cells.size() == flowModel_().numTotalDof()) {
201 // We are on the full domain.
202 resetSystem_();
203 }
204 else {
205 resetSystem_(domain);
206 }
207
208 linearize_(domain);
209 }
210
215 { }
216
224 void setResAndJacobi(VectorBlock& res, MatrixBlock& bMat, const ADVectorBlock& resid) const
225 {
226 // Scalar local residual
227 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
228 res[eqIdx] = resid[eqIdx].value();
229 }
230
231 // A[dofIdx][focusDofIdx][eqIdx][pvIdx] is the partial derivative of the residual function 'eqIdx' for the
232 // degree of freedom 'dofIdx' with regard to the focus variable 'pvIdx' of the degree of freedom 'focusDofIdx'
233 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
234 for (unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
235 bMat[eqIdx][pvIdx] = resid[eqIdx].derivative(pvIdx);
236 }
237 }
238 }
239
244 {
245 for (auto& bdyInfo : boundaryInfo_) {
246 // Get boundary information from problem
247 const auto& mechBC = problem_().mechBoundaryCondition(bdyInfo.cell, bdyInfo.dir);
248
249 // Strip the unnecessary (and zero anyway) derivatives off displacement
250 std::vector<double> displacement(3, 0.0);
251 for (std::size_t ii = 0; ii < displacement.size(); ++ii) {
252 displacement[ii] = mechBC.displacement[ii].value();
253 }
254
255 // Update boundary information
256 bdyInfo.bcdata.type = mechBC.type;
257 bdyInfo.bcdata.displacement = displacement;
258 bdyInfo.bcdata.shearModulus = mechBC.shearModulus;
259 bdyInfo.bcdata.distance = mechBC.distance;
260 }
261 }
262
267 {
268 OPM_TIMEBLOCK(updateStressInfoTPSA);
269
270 if (stressInfo_.empty()) {
271 return;
272 }
273
274 const auto& geoMechModel = geoMechModel_();
275 auto& problem = problem_();
276 const unsigned int numCells = fullDomain_.cells.size();
277
278#ifdef _OPENMP
279#pragma omp parallel for
280#endif
281 // Interior traction of every cell, one per face to its neighbors
282 for (unsigned ii = 0; ii < numCells; ++ii) {
283 const unsigned globI = fullDomain_.cells[ii];
284 const MaterialState& materialStateIn =
285 geoMechModel.materialState(globI, /*timeIdx=*/0);
286
287 short loc = 0;
288 for (const auto& nbInfo : neighborInfo_[globI]) {
289 const unsigned globJ = nbInfo.neighbor;
290 const MaterialState& materialStateEx =
291 geoMechModel.materialState(globJ, /*timeIdx=*/0);
292
293 // Compute local face term
294 ADVectorBlock adres(0.0);
295 LocalResidual::computeFaceTerm(adres,
296 materialStateIn,
297 materialStateEx,
298 problem,
299 globI,
300 globJ);
301 adres *= nbInfo.faceArea;
302
303 // Insert interior traction vector
304 // OBS: Assume traction vector is the three first entries in residual!
305 stressInfo_[globI][loc].faceNormal = problem.cellFaceNormal(globI, globJ);
306 stressInfo_[globI][loc].faceArea = nbInfo.faceArea;
307 for (unsigned tractionIdx = 0; tractionIdx < 3; ++tractionIdx) {
308 stressInfo_[globI][loc].traction[tractionIdx] = adres[tractionIdx].value();
309 }
310 ++loc;
311 }
312 }
313
314 // Boundary traction
315 for (const auto& bdyInfo : boundaryInfo_) {
316 const unsigned globI = bdyInfo.cell;
317 const MaterialState& materialStateIn = geoMechModel.materialState(globI, /*timeIdx=*/0);
318
319 // Compute local boundary condition
320 ADVectorBlock adres(0.0);
321 LocalResidual::computeBoundaryTerm(adres,
322 materialStateIn,
323 bdyInfo.bcdata,
324 problem,
325 globI);
326 adres *= bdyInfo.bcdata.faceArea;
327
328 // Insert boundary traction vector
329 // OBS: Assume traction vector is the three first entries in residual!
330 const short loc = neighborInfo_[globI].size() + bdyInfo.bfIndex;
331 stressInfo_[globI][loc].faceNormal =
332 problem.cellFaceNormalBoundary(globI, bdyInfo.bfIndex);
333 stressInfo_[globI][loc].faceArea = bdyInfo.bcdata.faceArea;
334 for (unsigned tractionIdx = 0; tractionIdx < 3; ++tractionIdx) {
335 stressInfo_[globI][loc].traction[tractionIdx] = adres[tractionIdx].value();
336 }
337 }
338 }
339
340 // ///
341 // Public get and set functions
342 // ///
348 const SparseMatrixAdapter& jacobian() const
349 { return *jacobian_; }
350
356 SparseMatrixAdapter& jacobian()
357 { return *jacobian_; }
358
364 const GlobalEqVector& residual() const
365 { return residual_; }
366
372 GlobalEqVector& residual()
373 { return residual_; }
374
384 { return linearizationType_; }
385
391 const auto& getStressInfo() const
392 {
393 return stressInfo_;
394 }
395
403 std::map<unsigned, Constraints> constraintsMap() const
404 { return {}; }
405
412 { linearizationType_ = linearizationType; }
413
414private:
415 // ///
416 // Private functions
417 // ///
424 void createMatrix_()
425 {
426 OPM_TIMEBLOCK(createMatrixTPSA);
427
428 // If the Jacobian has been initialize before, we jump out
429 if (!neighborInfo_.empty()) {
430 return;
431 }
432
433 // Init. the stencil
434 const auto& flowModel = flowModel_();
435 Stencil stencil(gridView_(), flowModel.dofMapper());
436
437 // Build up sparsity patterns and neighboring information for Jacobian and linearization
438 std::vector<std::set<unsigned>> sparsityPattern(flowModel.numTotalDof());
439 unsigned numCells = flowModel.numTotalDof();
440 neighborInfo_.reserve(numCells, 6 * numCells);
441 std::vector<NeighborInfo> loc_nbinfo;
442
443 stressInfo_.reserve(numCells, 6 * numCells);
444 std::vector<StressInfo> loc_stressinfo;
445 StressInfoVector nullTraction(0.0);
446 StressInfoVector nullFaceNormal(0.0);
447 for (const auto& elem : elements(gridView_())) {
448 // Loop over primary dofs in the element
449 stencil.update(elem);
450
451 for (unsigned primaryDofIdx = 0; primaryDofIdx < stencil.numPrimaryDof(); ++primaryDofIdx) {
452 // Build up neighboring information for curret primary dof
453 const unsigned myIdx = stencil.globalSpaceIndex(primaryDofIdx);
454 loc_nbinfo.resize(stencil.numDof() - 1);
455
456 // Build information for stress output
457 const int numFaces = stencil.numBoundaryFaces() + stencil.numInteriorFaces();
458 loc_stressinfo.resize(numFaces);
459
460 for (unsigned dofIdx = 0; dofIdx < stencil.numDof(); ++dofIdx) {
461 // NOTE: NeighborInfo could/should be expanded with cell face parameters located in problem_()
462 // needed when computing face terms in LocalResidual
463 const unsigned neighborIdx = stencil.globalSpaceIndex(dofIdx);
464 sparsityPattern[myIdx].insert(neighborIdx);
465 if (dofIdx > 0) {
466 const auto scvfIdx = dofIdx - 1;
467 const auto& scvf = stencil.interiorFace(scvfIdx);
468 const Scalar area = scvf.area();
469 loc_nbinfo[dofIdx - 1] = NeighborInfo{ neighborIdx, area, BlockAddress{} };
470
471 int faceId = scvf.dirId();
472 loc_stressinfo[dofIdx - 1] =
473 StressInfo{faceId, nullTraction, nullFaceNormal, area};
474 }
475 }
476
477 // Insert local neighbor info
478 neighborInfo_.appendRow(loc_nbinfo.begin(), loc_nbinfo.end());
479
480 // Boundary condition information
481 unsigned bfIndex = 0;
482 for (const auto& intersection : intersections(gridView_(), elem)) {
483 if (intersection.boundary()) {
484 // Get boundary face direction
485 const auto& bf = stencil.boundaryFace(bfIndex);
486 const int dir_id = bf.dirId();
487 const auto bfArea = bf.area();
488
489 // Initialize boundary information for stress output container
490 // OBS: NNCs are not implemented with TPSA, hence traction and face
491 // normal vector will stay zero for NNC connections!
492 loc_stressinfo[stencil.numInteriorFaces() + bfIndex] =
493 StressInfo{dir_id, nullTraction, nullFaceNormal, bfArea};
494
495 // Skip NNCs
496 if (dir_id < 0) {
497 continue;
498 }
499
500 // Get boundary information from problem()
501 const auto& mechBC = problem_().mechBoundaryCondition(myIdx, dir_id);
502
503 // Strip the unnecessary (and zero anyway) derivatives off displacement
504 std::vector<double> displacement(3, 0.0);
505 for (std::size_t ii = 0; ii < displacement.size(); ++ii) {
506 displacement[ii] = mechBC.displacement[ii].value();
507 }
508
509 // Insert boundary condition data in container
510 BoundaryConditionData bcdata{mechBC.type,
511 displacement,
512 mechBC.shearModulus,
513 mechBC.distance,
514 bfIndex,
515 bfArea};
516 boundaryInfo_.push_back( { myIdx, dir_id, bfIndex, bcdata } );
517 ++bfIndex;
518 continue;
519 }
520 if (!intersection.neighbor()) {
521 ++bfIndex;
522 continue;
523 }
524 }
525 stressInfo_.appendRow(loc_stressinfo.begin(), loc_stressinfo.end());
526 }
527 }
528
529 // Allocate Jacobian matrix and pointers to its sub-blocks
530 jacobian_ = std::make_unique<SparseMatrixAdapter>(simulator_());
531 diagMatAddress_.resize(numCells);
532 jacobian_->reserve(sparsityPattern);
533 for (unsigned globI = 0; globI < numCells; globI++) {
534 const auto& nbInfos = neighborInfo_[globI];
535 diagMatAddress_[globI] = jacobian_->blockAddress(globI, globI);
536 for (auto& nbInfo : nbInfos) {
537 nbInfo.matBlockAddress = jacobian_->blockAddress(nbInfo.neighbor, globI);
538 }
539 }
540
541 // Create full domain
542 fullDomain_.cells.resize(numCells);
543 std::iota(fullDomain_.cells.begin(), fullDomain_.cells.end(), 0);
544 }
545
551 template <class SubDomainType>
552 void linearize_(const SubDomainType& domain)
553 {
554 OPM_TIMEBLOCK(linearizeTPSA);
555
556 // Extract misc. variables used in linearization
557 const auto& flowModel = flowModel_();
558 const auto& geoMechModel = geoMechModel_();
559 auto& problem = problem_();
560 const unsigned int numCells = domain.cells.size();
561
562#ifdef _OPENMP
563#pragma omp parallel for
564#endif
565 // Loop over cells in the domain and compute local residual and jacobian
566 for (unsigned ii = 0; ii < numCells; ++ii) {
567 OPM_TIMEBLOCK_LOCAL(linearizationForEachCellTPSA, Subsystem::Assembly);
568
569 const unsigned globI = domain.cells[ii];
570 const auto& nbInfos = neighborInfo_[globI];
571 VectorBlock res(0.0);
572 MatrixBlock bMat(0.0);
573 ADVectorBlock adres(0.0);
574 const MaterialState& materialStateIn = geoMechModel.materialState(globI, /*timeIdx=*/0);
575
576 // ///
577 // Face term
578 // ///
579 {
580 OPM_TIMEBLOCK_LOCAL(faceCalculationForEachCellTPSA, Subsystem::Assembly);
581
582 // Loop over neighboring cells
583 for (auto& nbInfo : nbInfos) {
584 OPM_TIMEBLOCK_LOCAL(calculationForEachFaceTPSA, Subsystem::Assembly);
585
586 // Reset local residual and Jacobian
587 res = 0.0;
588 bMat = 0.0;
589 adres = 0.0;
590
591 // Neighbor information
592 const unsigned globJ = nbInfo.neighbor;
593 assert(globJ != globI);
594 const MaterialState& materialStateEx = geoMechModel.materialState(globJ, /*timeIdx=*/0);
595
596 // Compute local face term
597 LocalResidual::computeFaceTerm(adres,
598 materialStateIn,
599 materialStateEx,
600 problem,
601 globI,
602 globJ);
603 adres *= nbInfo.faceArea;
604
605 // Extract residual and sub-block Jacobian entries from computed AD residual
606 setResAndJacobi(res, bMat, adres);
607
608 // Insert into global residual
609 residual_[globI] += res;
610
611 // Insert contribution to (globI, globI) sub-block
612 // SparseAdapter syntax: jacobian_->addToBlock(globI, globI, bMat);
613 *diagMatAddress_[globI] += bMat;
614
615 // Insert contribution to (globJ, globI) sub-block
616 // Note: since LocalResidual::computeFaceTerm have Evaluation on globI primary variables, it is
617 // natural to insert Jacobian entries for (globJ, globI) here, since we only need to flip the signs
618 // in the calculated face terms
619 // SparseAdapter syntax: jacobian_->addToBlock(globJ, globI, bMat);
620 bMat *= -1.0;
621 *nbInfo.matBlockAddress += bMat;
622 }
623 }
624
625 // ///
626 // Volume term
627 // //
628 adres = 0.0;
629 {
630 OPM_TIMEBLOCK_LOCAL(computeVolumeTerm, Subsystem::Assembly);
631
632 // Compute local volume term
633 LocalResidual::computeVolumeTerm(adres,
634 materialStateIn,
635 problem,
636 globI);
637 }
638 const double volume = flowModel.dofTotalVolume(globI);
639 adres *= volume;
640
641 // Extract residual and sub-block Jacobian entries from computed AD residual
642 setResAndJacobi(res, bMat, adres);
643
644 // Insert in global residual
645 residual_[globI] += res;
646
647 // Insert contribution to (globI, globI) sub-block
648 // SparseAdapter syntax: jacobian_->addToBlock(globI, globI, bMat);
649 *diagMatAddress_[globI] += bMat;
650
651 // ///
652 // Source term
653 // ///
654 res = 0.0;
655 bMat = 0.0;
656 adres = 0.0;
657
658 // Compute local source term
659 LocalResidual::computeSourceTerm(adres,
660 problem,
661 globI,
662 0);
663 adres *= -volume;
664
665 // Extract residual and sub-block Jacobian entries from computed AD residual
666 setResAndJacobi(res, bMat, adres);
667
668 // Insert into global residual
669 residual_[globI] += res;
670
671 // Insert contribution to (globI, globI) sub-block
672 // SparseAdapter syntax: jacobian_->addToBlock(globI, globI, bMat);
673 *diagMatAddress_[globI] += bMat;
674 } // globI loop
675
676 // ///
677 // Boundary term
678 // ///
679 for (const auto& bdyInfo : boundaryInfo_) {
680 VectorBlock res(0.0);
681 MatrixBlock bMat(0.0);
682 ADVectorBlock adres(0.0);
683 const unsigned globI = bdyInfo.cell;
684 const MaterialState& materialStateIn = geoMechModel.materialState(globI, /*timeIdx=*/0);
685
686 // Compute local boundary condition
687 LocalResidual::computeBoundaryTerm(adres,
688 materialStateIn,
689 bdyInfo.bcdata,
690 problem,
691 globI);
692 adres *= bdyInfo.bcdata.faceArea;
693
694 // Extract residual and sub-block Jacobian entries from computed AD residual
695 setResAndJacobi(res, bMat, adres);
696
697 // Insert in global residual
698 residual_[globI] += res;
699
700 // Insert contribution to (globI, globI) sub-block
701 // SparseAdapter syntax: jacobian_->addToBlock(globI, globI, bMat);
702 *diagMatAddress_[globI] += bMat;
703 }
704 }
705
709 void initFirstIteration_()
710 {
711 // initialize the BCRS matrix for the Jacobian of the residual function
712 createMatrix_();
713
714 // initialize the Jacobian matrix and the vector for the residual function
715 residual_.resize(flowModel_().numTotalDof());
716 resetSystem_();
717 }
718
722 void resetSystem_()
723 {
724 // Set residual vector entries to zero
725 residual_ = 0.0;
726
727 // Set all Jacobian matrix entries to zero
728 jacobian_->clear();
729 }
730
731 // ///
732 // Private get functions
733 // ///
739 Simulator& simulator_()
740 { return *simulatorPtr_; }
741
747 const Simulator& simulator_() const
748 { return *simulatorPtr_; }
749
755 Problem& problem_()
756 { return simulator_().problem(); }
757
763 const Problem& problem_() const
764 { return simulator_().problem(); }
765
771 FlowModel& flowModel_()
772 { return simulator_().model(); }
773
779 const FlowModel& flowModel_() const
780 { return simulator_().model(); }
781
787 GeomechModel& geoMechModel_()
788 { return problem_().geoMechModel(); }
789
795 const GeomechModel& geoMechModel_() const
796 { return problem_().geoMechModel(); }
797
803 const GridView& gridView_() const
804 { return problem_().gridView(); }
805
806 Simulator* simulatorPtr_{};
807 LinearizationType linearizationType_{};
808
809 std::vector<BlockAddress> diagMatAddress_{};
810 std::unique_ptr<SparseMatrixAdapter> jacobian_{};
811 GlobalEqVector residual_;
812
813 //
814 // Helper structs
815 //
819 struct NeighborInfo
820 {
821 unsigned int neighbor;
822 double faceArea;
823 BlockAddress matBlockAddress;
824 };
825 SparseTable<NeighborInfo> neighborInfo_{};
826
830 struct StressInfo
831 {
832 int faceId;
833 StressInfoVector traction;
834 StressInfoVector faceNormal;
835 double faceArea;
836 };
837
838 SparseTable<StressInfo> stressInfo_{};
839
843 struct BoundaryConditionData
844 {
845 BCMECHType type;
846 std::vector<double> displacement;
847 Scalar shearModulus;
848 Scalar distance;
849 unsigned boundaryFaceIndex;
850 double faceArea;
851 };
852
856 struct BoundaryInfo
857 {
858 unsigned int cell;
859 int dir;
860 unsigned int bfIndex;
861 BoundaryConditionData bcdata;
862 };
863 std::vector<BoundaryInfo> boundaryInfo_;
864
868 struct FullDomain
869 {
870 std::vector<int> cells;
871 std::vector<bool> interior;
872 };
873 FullDomain fullDomain_;
874}; // class TpsaLinearizer
875
876} // namespace Opm
877
878#endif
Linearizes TPSA equations and generates system matrix and residual for linear solver.
Definition: tpsalinearizer.hpp:53
GlobalEqVector & residual()
Get residual vector.
Definition: tpsalinearizer.hpp:372
const SparseMatrixAdapter & jacobian() const
Get Jacobian matrix.
Definition: tpsalinearizer.hpp:348
const GlobalEqVector & residual() const
Get residual vector.
Definition: tpsalinearizer.hpp:364
void eraseMatrix()
Causes the Jacobian matrix to be recreated from scratch before the next iteration.
Definition: tpsalinearizer.hpp:110
void resetSystem_(const SubDomainType &domain)
Initializing and/or reset residual and Jacobian.
Definition: tpsalinearizer.hpp:129
std::map< unsigned, Constraints > constraintsMap() const
Get constraints map.
Definition: tpsalinearizer.hpp:403
void updateBoundaryConditionData()
Update boundary condition information.
Definition: tpsalinearizer.hpp:243
void updateStressInfo()
Compute the stress (or traction) for mechanics output.
Definition: tpsalinearizer.hpp:266
SparseMatrixAdapter & jacobian()
Get Jacobian matrix.
Definition: tpsalinearizer.hpp:356
TpsaLinearizer()
Constructor.
Definition: tpsalinearizer.hpp:85
void linearizeDomain(const SubDomainType &domain)
Linearize the non-linear system for the spatial domain.
Definition: tpsalinearizer.hpp:190
void linearizeDomain()
Linearize the non-linear system for the spatial domain.
Definition: tpsalinearizer.hpp:155
void finalize()
Finalize creation of Jacobian matrix and make ready for linear solver.
Definition: tpsalinearizer.hpp:118
const auto & getStressInfo() const
Definition: tpsalinearizer.hpp:391
void setLinearizationType(LinearizationType linearizationType)
Set linearization type.
Definition: tpsalinearizer.hpp:411
const LinearizationType & getLinearizationType() const
Get linearization type.
Definition: tpsalinearizer.hpp:383
void linearizeAuxiliaryEquations()
Linearize auxillary equation.
Definition: tpsalinearizer.hpp:214
void init(Simulator &simulator)
Initialize the linearizer.
Definition: tpsalinearizer.hpp:98
void linearize()
Linearize the non-linear system.
Definition: tpsalinearizer.hpp:143
void setResAndJacobi(VectorBlock &res, MatrixBlock &bMat, const ADVectorBlock &resid) const
Extract local residuals and sub-block Jacobians from locally computed AD residual.
Definition: tpsalinearizer.hpp:224
Definition: blackoilbioeffectsmodules.hh:45
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
Definition: linearizationtype.hh:34