141
130
if (N != b.size())
142
131
error("Incorrect dimension of matrix for application of boundary conditions. Did you assemble it on a different mesh?");
144
// Set message string
146
if (method == topological)
147
s = "Computing Dirichlet boundary values";
148
else if (method == geometrical)
149
s = "Computing Dirichlet boundary values (geometrical approach)";
151
s = "Computing Dirichlet boundary values (pointwise approach)";
153
// Make sure we have the facet - cell connectivity
154
const uint D = _mesh.topology().dim();
155
if (method == topological)
156
_mesh.init(D - 1, D);
133
// A map to hold the mapping from boundary dofs to boundary values
134
std::map<uint, real> boundary_values;
158
136
// Create local data for application of boundary conditions
159
137
BoundaryCondition::LocalData data(form, _mesh, dof_map, sub_system);
161
// A map to hold the mapping from boundary dofs to boundary values
162
std::map<uint, real> boundary_values;
165
if (method == pointwise)
167
Progress p(s, _mesh.size(D));
168
for (CellIterator cell(_mesh); !cell.end(); ++cell)
170
computeBCPointwise(boundary_values, *cell, data);
176
// Iterate over the facets of the mesh
177
Progress p(s, _mesh.size(D - 1));
178
for (FacetIterator facet(_mesh); !facet.end(); ++facet)
180
// Skip facets not inside the sub domain
181
if ((*sub_domains)(*facet) != sub_domain)
188
if (method == topological)
189
computeBCTopological(boundary_values, *facet, data);
191
computeBCGeometrical(boundary_values, *facet, data);
139
// Compute dofs and values
140
computeBC(boundary_values, data);
198
142
// Copy boundary value data to arrays
199
143
uint* dofs = new uint[boundary_values.size()];
214
158
for (uint i = 0; i < boundary_values.size(); i++)
215
159
values[i] -= x_values[i];
218
162
message("Applying boundary conditions to linear system.");
220
164
// Modify RHS vector (b[i] = value)
221
165
b.set(values, boundary_values.size(), dofs);
223
167
// Modify linear system (A_ii = 1)
224
168
A.ident(boundary_values.size(), dofs);
226
170
// Clear temporary arrays
228
172
delete [] values;
230
174
// Finalise changes to A
233
177
// Finalise changes to b
236
180
//-----------------------------------------------------------------------------
181
void DirichletBC::zero(GenericMatrix& A, const Form& form)
183
zero(A, form.dofMaps()[1], form.form());
185
//-----------------------------------------------------------------------------
186
void DirichletBC::zero(GenericMatrix& A, const DofMap& dof_map, const ufc::form& form)
189
const uint N = dof_map.global_dimension();
190
if (N != A.size(0) || N != A.size(1))
191
error("Incorrect dimension of matrix for application of boundary conditions. Did you assemble it on a different mesh?");
193
// A map to hold the mapping from boundary dofs to boundary values
194
std::map<uint, real> boundary_values;
196
// Create local data for application of boundary conditions
197
BoundaryCondition::LocalData data(form, _mesh, dof_map, sub_system);
199
// Compute dofs and values
200
computeBC(boundary_values, data);
202
// Copy boundary value data to arrays
203
uint* dofs = new uint[boundary_values.size()];
204
std::map<uint, real>::const_iterator boundary_value;
206
for (boundary_value = boundary_values.begin(); boundary_value != boundary_values.end(); ++boundary_value)
207
dofs[i++] = boundary_value->first;
209
// Modify linear system (A_ii = 1)
210
A.zero(boundary_values.size(), dofs);
212
// Finalise changes to A
215
// Clear temporary arrays
218
//-----------------------------------------------------------------------------
237
219
Mesh& DirichletBC::mesh()
241
223
//-----------------------------------------------------------------------------
242
224
void DirichletBC::initFromSubDomain(SubDomain& sub_domain)
244
cout << "Creating sub domain markers for boundary condition." << endl;
226
dolfin_assert(facets.size() == 0);
228
// FIXME: This can be made more efficient, we should be able to
229
// FIXME: extract the facets without first creating a MeshFunction on
230
// FIXME: the entire mesh and then extracting the subset. This is done
231
// FIXME: mainly for convenience (we may reuse mark() in SubDomain).
246
233
// Create mesh function for sub domain markers on facets
247
_mesh.init(_mesh.topology().dim() - 1);
248
sub_domains = new MeshFunction<uint>(_mesh, _mesh.topology().dim() - 1);
249
sub_domains_local = true;
234
const uint dim = _mesh.topology().dim();
236
MeshFunction<uint> sub_domains(_mesh, dim - 1);
251
238
// Mark everything as sub domain 1
254
241
// Mark the sub domain as sub domain 0
255
sub_domain.mark(*sub_domains, 0);
242
sub_domain.mark(sub_domains, 0);
244
// Initialize from mesh function
245
initFromMeshFunction(sub_domains, 0);
247
//-----------------------------------------------------------------------------
248
void DirichletBC::initFromMeshFunction(MeshFunction<uint>& sub_domains,
251
dolfin_assert(facets.size() == 0);
253
// Make sure we have the facet - cell connectivity
254
const uint dim = _mesh.topology().dim();
255
_mesh.init(dim - 1, dim);
257
// Build set of boundary facets
258
for (FacetIterator facet(_mesh); !facet.end(); ++facet)
260
// Skip facets not on this boundary
261
if (sub_domains(*facet) != sub_domain)
264
// Get cell to which facet belongs (there may be two, but pick first)
265
Cell cell(_mesh, facet->entities(dim)[0]);
267
// Get local index of facet with respect to the cell
268
const uint facet_number = cell.index(*facet);
271
facets.push_back(std::pair<uint, uint>(cell.index(), facet_number));
257
274
//-----------------------------------------------------------------------------
258
275
void DirichletBC::initFromMesh(uint sub_domain)
293
310
//-----------------------------------------------------------------------------
311
void DirichletBC::computeBC(std::map<uint, real>& boundary_values,
312
BoundaryCondition::LocalData& data)
318
computeBCTopological(boundary_values, data);
321
computeBCGeometric(boundary_values, data);
324
computeBCPointwise(boundary_values, data);
327
error("Unknown method for application of boundary conditions.");
330
//-----------------------------------------------------------------------------
294
331
void DirichletBC::computeBCTopological(std::map<uint, real>& boundary_values,
296
332
BoundaryCondition::LocalData& data)
298
// Get cell to which facet belongs (there may be two, but pick first)
299
Cell cell(_mesh, facet.entities(facet.dim() + 1)[0]);
300
UFCCell ufc_cell(cell);
302
// Get local index of facet with respect to the cell
303
const uint local_facet = cell.index(facet);
305
// Interpolate function on cell
306
g.interpolate(data.w, ufc_cell, *data.finite_element, cell, local_facet);
308
// Tabulate dofs on cell
309
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
311
// Tabulate which dofs are on the facet
312
data.dof_map->tabulate_facet_dofs(data.facet_dofs, local_facet);
316
cout << endl << "Handling BC's for:" << endl;
317
cout << "Cell: " << facet.entities(facet.dim() + 1)[0] << endl;
318
cout << "Facet: " << local_facet << endl;
321
// Pick values for facet
322
for (uint i = 0; i < data.dof_map->num_facet_dofs(); i++)
334
// Iterate over facets
335
Progress p("Computing Dirichlet boundary values, topological search", facets.size());
336
for (uint f = 0; f < facets.size(); f++)
324
const uint dof = data.offset + data.cell_dofs[data.facet_dofs[i]];
325
const real value = data.w[data.facet_dofs[i]];
326
boundary_values[dof] = value;
327
//cout << "Setting BC value: i = " << i << ", dof = " << dof << ", value = " << value << endl;
338
// Get cell number and local facet number
339
uint cell_number = facets[f].first;
340
uint facet_number = facets[f].second;
343
Cell cell(_mesh, cell_number);
344
UFCCell ufc_cell(cell);
346
// Interpolate function on cell
347
g.interpolate(data.w, ufc_cell, *data.finite_element, cell, facet_number);
349
// Tabulate dofs on cell
350
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
352
// Tabulate which dofs are on the facet
353
data.dof_map->tabulate_facet_dofs(data.facet_dofs, facet_number);
357
cout << endl << "Handling BC's for:" << endl;
358
cout << "Cell: " << facet.entities(facet.dim() + 1)[0] << endl;
359
cout << "Facet: " << local_facet << endl;
362
// Pick values for facet
363
for (uint i = 0; i < data.dof_map->num_facet_dofs(); i++)
365
const uint dof = data.offset + data.cell_dofs[data.facet_dofs[i]];
366
const real value = data.w[data.facet_dofs[i]];
367
boundary_values[dof] = value;
368
//cout << "Setting BC value: i = " << i << ", dof = " << dof << ", value = " << value << endl;
331
374
//-----------------------------------------------------------------------------
332
void DirichletBC::computeBCGeometrical(std::map<uint, real>& boundary_values,
334
BoundaryCondition::LocalData& data)
375
void DirichletBC::computeBCGeometric(std::map<uint, real>& boundary_values,
376
BoundaryCondition::LocalData& data)
336
// Loop the vertices associated with the facet
337
for (VertexIterator vertex(facet); !vertex.end(); ++vertex)
378
// Initialize facets, needed for geometric search
379
message("Computing facets, needed for geometric application of boundary conditions.");
380
_mesh.init(_mesh.topology().dim() - 1);
382
// Iterate over facets
383
Progress p("Computing Dirichlet boundary values, geometric search", facets.size());
384
for (uint f = 0; f < facets.size(); f++)
339
// Loop the cells associated with the vertex
340
for (CellIterator c(*vertex); !c.end(); ++c)
386
// Get cell number and local facet number
387
uint cell_number = facets[f].first;
388
uint facet_number = facets[f].second;
391
Cell cell(_mesh, cell_number);
392
Facet facet(_mesh, cell.entities(_mesh.topology().dim() - 1)[facet_number]);
394
// Loop the vertices associated with the facet
395
for (VertexIterator vertex(facet); !vertex.end(); ++vertex)
342
UFCCell ufc_cell(*c);
344
// Interpolate function on cell
345
g.interpolate(data.w, ufc_cell, *data.finite_element, *c);
347
// Tabulate dofs on cell, and their coordinates
348
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
349
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
351
// Loop all dofs on cell
352
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
397
// Loop the cells associated with the vertex
398
for (CellIterator c(*vertex); !c.end(); ++c)
354
// Check if the coordinates are on current facet and thus on boundary
355
if (!onFacet(data.coordinates[i], facet))
358
// Set boundary value
359
const uint dof = data.offset + data.cell_dofs[i];
360
const real value = data.w[i];
361
boundary_values[dof] = value;
400
UFCCell ufc_cell(*c);
402
// Interpolate function on cell
403
g.interpolate(data.w, ufc_cell, *data.finite_element, *c);
405
// Tabulate dofs on cell, and their coordinates
406
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
407
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
409
// Loop all dofs on cell
410
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
412
// Check if the coordinates are on current facet and thus on boundary
413
if (!onFacet(data.coordinates[i], facet))
416
// Set boundary value
417
const uint dof = data.offset + data.cell_dofs[i];
418
const real value = data.w[i];
419
boundary_values[dof] = value;
366
425
//-----------------------------------------------------------------------------
367
426
void DirichletBC::computeBCPointwise(std::map<uint, real>& boundary_values,
369
427
BoundaryCondition::LocalData& data)
371
429
dolfin_assert(user_sub_domain);
373
// Interpolate function on cell
374
UFCCell ufc_cell(cell);
375
g.interpolate(data.w, ufc_cell, *data.finite_element, cell);
377
// Tabulate dofs on cell, and their coordinates
378
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
379
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
381
// Loop all dofs on cell
382
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
431
// Iterate over cells
432
Progress p("Computing Dirichlet boundary values, pointwise search", facets.size());
433
for (CellIterator cell(_mesh); !cell.end(); ++cell)
384
// Check if the coordinates are part of the sub domain
385
if ( !user_sub_domain->inside(data.coordinates[i], false) )
435
// Interpolate function on cell
436
UFCCell ufc_cell(*cell);
437
g.interpolate(data.w, ufc_cell, *data.finite_element, *cell);
439
// Tabulate dofs on cell, and their coordinates
440
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
441
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
443
// Loop all dofs on cell
444
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
446
// Check if the coordinates are part of the sub domain
447
if ( !user_sub_domain->inside(data.coordinates[i], false) )
450
// Set boundary value
451
const uint dof = data.offset + data.cell_dofs[i];
452
const real value = data.w[i];
453
boundary_values[dof] = value;
388
// Set boundary value
389
const uint dof = data.offset + data.cell_dofs[i];
390
const real value = data.w[i];
391
boundary_values[dof] = value;
394
459
//-----------------------------------------------------------------------------
446
511
//-----------------------------------------------------------------------------
447
void DirichletBC::zero(GenericMatrix& A, const Form& form)
449
zero(A, form.dofMaps()[1], form.form());
451
//-----------------------------------------------------------------------------
452
void DirichletBC::zero(GenericMatrix& A, const DofMap& dof_map, const ufc::form& form)
454
// FIXME: How do we reuse the dof map for u?
457
if (method == topological)
458
s = "Applying Dirichlet boundary conditions to linear system";
459
else if (method == geometrical)
460
s = "Applying Dirichlet boundary conditions to linear system (geometrical approach)";
462
s = "Applying Dirichlet boundary conditions to linear system (pointwise approach)";
464
// Make sure we have the facet - cell connectivity
465
const uint D = _mesh.topology().dim();
466
if (method == topological)
467
_mesh.init(D - 1, D);
469
// Create local data for application of boundary conditions
470
BoundaryCondition::LocalData data(form, _mesh, dof_map, sub_system);
472
// A map to hold the mapping from boundary dofs to boundary values
473
std::map<uint, real> boundary_values;
475
if (method == pointwise)
477
Progress p(s, _mesh.size(D));
478
for (CellIterator cell(_mesh); !cell.end(); ++cell)
480
computeBCPointwise(boundary_values, *cell, data);
486
// Iterate over the facets of the mesh
487
Progress p("Applying Dirichlet boundary conditions", _mesh.size(D - 1));
488
for (FacetIterator facet(_mesh); !facet.end(); ++facet)
490
// Skip facets not inside the sub domain
491
if ((*sub_domains)(*facet) != sub_domain)
498
if (method == topological)
499
computeBCTopological(boundary_values, *facet, data);
501
computeBCGeometrical(boundary_values, *facet, data);
508
// Copy boundary value data to arrays
509
uint* dofs = new uint[boundary_values.size()];
510
std::map<uint, real>::const_iterator boundary_value;
512
for (boundary_value = boundary_values.begin(); boundary_value != boundary_values.end(); ++boundary_value)
513
dofs[i++] = boundary_value->first;
515
// Modify linear system (A_ii = 1)
516
A.zero(boundary_values.size(), dofs);
518
// Finalise changes to A
521
// Clear temporary arrays
524
//-----------------------------------------------------------------------------
525
512
void DirichletBC::setSubSystem(SubSystem sub_system)
527
514
this->sub_system = sub_system;