15
19
// --------------------------------------------------------------------
16
20
// --------------------------------------------------------------------
17
21
ImplicitSolveOperator::
18
ImplicitSolveOperator(ATC_Coupling * atc,
19
/*const*/ FE_Engine * feEngine,
20
const PhysicsModel * physicsModel)
23
physicsModel_(physicsModel)
22
ImplicitSolveOperator(double alpha, double dt)
25
29
// Nothing else to do here
28
32
// --------------------------------------------------------------------
34
// --------------------------------------------------------------------
36
ImplicitSolveOperator::operator * (const DENS_VEC & x) const
38
// This method uses a matrix-free approach to approximate the
39
// multiplication by matrix A in the matrix equation Ax=b, where the
40
// matrix equation results from an implicit treatment of the
41
// fast field. In brief, if the ODE for the fast field can be written:
45
// A generalized discretization can be written:
47
// 1/dt * (x^n+1 - x^n) = alpha * R(x^n+1) + (1-alpha) * R(x^n)
49
// Taylor expanding the R(x^n+1) term and rearranging gives the
50
// equation to be solved for dx at each timestep:
52
// [1 - dt * alpha * dR/dx] * dx = dt * R(x^n)
54
// The operator defined in this method computes the left-hand side,
55
// given a vector dx. It uses a finite difference, matrix-free
56
// approximation of dR/dx * dx, giving:
58
// [1 - dt * alpha * dR/dx] * dx = dt * R(x^n)
59
// ~= dx - dt*alpha/epsilon * ( R(x^n + epsilon*dx) - R(x^n) )
62
double epsilon = (x.norm()>0.0) ? epsilon0_*x0_.norm()/x.norm():epsilon0_;
63
// Compute incremented vector x^n+1 = x^n + epsilon*dx
64
x_ = x0_ + epsilon * x;
67
// Compute full left hand side and return it
68
DENS_VEC Ax = x - dt_ * alpha_ / epsilon * (R_ - R0_);
72
// --------------------------------------------------------------------
74
// --------------------------------------------------------------------
76
ImplicitSolveOperator::r() const
78
return dt_ * R0_; // dt * R(T^n)
81
// --------------------------------------------------------------------
83
// --------------------------------------------------------------------
85
ImplicitSolveOperator::preconditioner() const
89
DIAG_MAT preconditioner(diag);
90
return preconditioner;
93
// --------------------------------------------------------------------
29
94
// --------------------------------------------------------------------
30
95
// FieldImplicitSolveOperator
31
96
// --------------------------------------------------------------------
32
97
// --------------------------------------------------------------------
33
98
FieldImplicitSolveOperator::
34
99
FieldImplicitSolveOperator(ATC_Coupling * atc,
35
/*const*/ FE_Engine * feEngine,
37
101
const FieldName fieldName,
38
102
const Array2D< bool > & rhsMask,
43
: ImplicitSolveOperator(atc, feEngine, physicsModel),
107
: ImplicitSolveOperator(alpha, dt),
44
108
fieldName_(fieldName),
45
fields_(fields), // ref to fields
110
physicsModel_(physicsModel),
111
fields0_(fields), // ref to fields
112
fields_ (fields), // copy of fields
51
// find field associated with ODE
116
const DENS_MAT & f = fields0_[fieldName_].quantity();
118
if (dof_ > 1) throw ATC_Error("Implicit solver operator can only handle scalar fields");
119
// create all to free map
120
int nNodes = f.nRows();
121
set<int> fixedNodes_ = atc_->prescribed_data_manager()->fixed_nodes(fieldName_);
123
vector<bool> tag(nNodes);
124
set<int>::const_iterator it; int i = 0;
125
for (i = 0; i < nNodes; ++i) { tag[i] = true; }
126
for (it=fixedNodes_.begin();it!=fixedNodes_.end();++it) {tag[*it]=false;}
128
for (i = 0; i < nNodes; ++i) { if (tag[i]) freeNodes_[i]= m++; }
129
//std::cout << " nodes " << n_ << " " << nNodes << "\n";
131
// Save current field
134
x_ = x0_; // initialize
136
// righthand side/forcing vector
52
137
rhsMask_.reset(NUM_FIELDS,NUM_FLUX);
54
139
for (int i = 0; i < rhsMask.nCols(); i++) {
55
140
rhsMask_(fieldName_,i) = rhsMask(fieldName_,i);
142
//std::cout << print_mask(rhsMask_) << "\n";
57
143
massMask_.reset(1);
58
144
massMask_(0) = fieldName_;
60
// Save off current field
61
TnVect_ = column(fields_[fieldName_].quantity(),0);
63
// Allocate vectors for fields and rhs
64
int nNodes = atc_->num_nodes();
68
int dof = fields_[fieldName_].nCols();
69
RnMap_ [fieldName_].reset(nNodes,dof);
70
RnpMap_[fieldName_].reset(nNodes,dof);
145
rhs_[fieldName_].reset(nNodes,dof_);
72
146
// Compute the RHS vector R(T^n)
73
// Set BCs on Rn, multiply by inverse mass and then extract its vector
74
atc_->compute_rhs_vector(rhsMask_, fields_, RnMap_,
75
FULL_DOMAIN, physicsModel_);
76
DENS_MAT & Rn = RnMap_[fieldName_].set_quantity();
77
atc_->prescribed_data_manager()
78
->set_fixed_dfield(time_, fieldName_, Rn);
79
atc_->apply_inverse_mass_matrix(Rn,fieldName_);
80
RnVect_ = column(Rn,0);
84
// --------------------------------------------------------------------
86
// --------------------------------------------------------------------
88
FieldImplicitSolveOperator::operator * (DENS_VEC x) const
90
// This method uses a matrix-free approach to approximate the
91
// multiplication by matrix A in the matrix equation Ax=b, where the
92
// matrix equation results from an implicit treatment of the
93
// fast field solve for the Two Temperature Model. In
94
// brief, if the ODE for the fast field can be written:
98
// A generalized discretization can be written:
100
// 1/dt * (T^n+1 - T^n) = alpha * R(T^n+1) + (1-alpha) * R(T^n)
102
// Taylor expanding the R(T^n+1) term and rearranging gives the
103
// equation to be solved for dT at each timestep:
105
// [1 - dt * alpha * dR/dT] * dT = dt * R(T^n)
107
// The operator defined in this method computes the left-hand side,
108
// given a vector dT. It uses a finite difference, matrix-free
109
// approximation of dR/dT * dT, giving:
111
// [1 - dt * alpha * dR/dT] * dT = dt * R(T^n)
112
// ~= dT - dt*alpha/epsilon * ( R(T^n + epsilon*dT) - R(T^n) )
117
double epsilon = (x.norm() > 0.0) ? epsilon0_ * TnVect_.norm()/x.norm() : epsilon0_;
119
// Compute incremented vector = T + epsilon*dT
120
fieldsNp1_[fieldName_] = TnVect_ + epsilon * x;
123
atc_->compute_rhs_vector(rhsMask_, fieldsNp1_, RnpMap_,
124
FULL_DOMAIN, physicsModel_);
125
DENS_MAT & Rnp = RnpMap_[fieldName_].set_quantity();
126
atc_->prescribed_data_manager()
127
->set_fixed_dfield(time_, fieldName_, Rnp);
128
atc_->apply_inverse_mass_matrix(Rnp,fieldName_);
129
RnpVect_ = column(Rnp,0);
131
// Compute full left hand side and return it
132
DENS_VEC Ax = x - dt_ * alpha_ / epsilon * (RnpVect_ - RnVect_);
136
// --------------------------------------------------------------------
138
// --------------------------------------------------------------------
140
FieldImplicitSolveOperator::rhs()
142
// Return dt * R(T^n)
143
return dt_ * RnVect_;
146
// --------------------------------------------------------------------
148
// --------------------------------------------------------------------
150
FieldImplicitSolveOperator::preconditioner(FIELDS & fields)
152
// Just create and return identity matrix
153
int nNodes = atc_->num_nodes();
154
DENS_VEC ones(nNodes);
156
DIAG_MAT identity(ones);
152
void FieldImplicitSolveOperator::to_all(const VECTOR &x, MATRIX &f) const
154
f.reset(x.nRows(),1);
155
for (int i = 0; i < x.nRows(); ++i) {
159
void FieldImplicitSolveOperator::to_free(const MATRIX &r, VECTOR &v) const
162
for (int i = 0; i < r.nRows(); ++i) {
167
FieldImplicitSolveOperator::R(const DENS_VEC &x, DENS_VEC &v ) const
169
DENS_MAT & f = fields_[fieldName_].set_quantity();
170
atc_->prescribed_data_manager()->set_fixed_field(time_, fieldName_, f);
172
atc_->compute_rhs_vector(rhsMask_,fields_,rhs_,FULL_DOMAIN,physicsModel_);
173
DENS_MAT & r = rhs_[fieldName_].set_quantity();
174
atc_->prescribed_data_manager()->set_fixed_dfield(time_, fieldName_, r);
175
atc_->apply_inverse_mass_matrix(r,fieldName_);
179
//std::cout << "# x "; for (int i = 0; i < n_; ++i) std::cout << x(i) << " "; std::cout << "\n";
180
//std::cout << "# f "; for (int i = 0; i < n; ++i) std::cout << f(i,0) << " "; std::cout << "\n";
181
std::cout << "# r "; for (int i = 0; i < n; ++i) std::cout << r(i,0) << " "; std::cout << "\n";
182
//std::cout << "# v "; for (int i = 0; i < n; ++i) std::cout << v(i) << " "; std::cout << "\n";
186
void FieldImplicitSolveOperator::solution(const DENS_MAT & dx, DENS_MAT &f) const
188
DENS_MAT & df = fields_[fieldName_].set_quantity();
189
to_all(column(dx,0),df);
190
atc_->prescribed_data_manager()->set_fixed_dfield(time_, fieldName_, df);
193
void FieldImplicitSolveOperator::rhs(const DENS_MAT & r, DENS_MAT &rhs) const
196
to_all(column(r,0),rhs);
160
200
} // namespace ATC