158
211
for (uint i = 0; i < boundary_values.size(); i++)
159
212
values[i] -= x_values[i];
162
215
message("Applying boundary conditions to linear system.");
164
217
// Modify RHS vector (b[i] = value)
165
218
b.set(values, boundary_values.size(), dofs);
167
220
// Modify linear system (A_ii = 1)
168
221
A.ident(boundary_values.size(), dofs);
170
223
// Clear temporary arrays
172
225
delete [] values;
174
227
// Finalise changes to A
177
230
// Finalise changes to b
180
233
//-----------------------------------------------------------------------------
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();
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
//-----------------------------------------------------------------------------
219
234
Mesh& DirichletBC::mesh()
223
238
//-----------------------------------------------------------------------------
224
void DirichletBC::initFromSubDomain(SubDomain& sub_domain)
239
void DirichletBC::init(SubDomain& sub_domain)
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).
241
cout << "Creating sub domain markers for boundary condition." << endl;
233
243
// Create mesh function for sub domain markers on facets
234
const uint dim = _mesh.topology().dim();
236
MeshFunction<uint> sub_domains(_mesh, dim - 1);
244
_mesh.init(_mesh.topology().dim() - 1);
245
sub_domains = new MeshFunction<uint>(_mesh, _mesh.topology().dim() - 1);
246
sub_domains_local = true;
238
248
// Mark everything as sub domain 1
241
251
// Mark the sub domain as sub domain 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));
274
//-----------------------------------------------------------------------------
275
void DirichletBC::initFromMesh(uint sub_domain)
277
dolfin_assert(facets.size() == 0);
279
cout << "Creating sub domain markers for boundary condition." << endl;
282
Array<uint>* facet_cells = _mesh.data().array("boundary facet cells");
283
Array<uint>* facet_numbers = _mesh.data().array("boundary facet numbers");
284
Array<uint>* indicators = _mesh.data().array("boundary indicators");
288
error("Mesh data \"boundary facet cells\" not available.");
290
error("Mesh data \"boundary facet numbers\" not available.");
292
error("Mesh data \"boundary indicators\" not available.");
295
const uint size = facet_cells->size();
296
dolfin_assert(size == facet_numbers->size());
297
dolfin_assert(size == indicators->size());
299
// Build set of boundary facets
300
for (uint i = 0; i < size; i++)
302
// Skip facets not on this boundary
303
if ((*indicators)[i] != sub_domain)
307
facets.push_back(std::pair<uint, uint>((*facet_cells)[i], (*facet_numbers)[i]));
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.");
252
sub_domain.mark(*sub_domains, 0);
330
254
//-----------------------------------------------------------------------------
331
255
void DirichletBC::computeBCTopological(std::map<uint, real>& boundary_values,
332
257
BoundaryCondition::LocalData& data)
335
if (facets.size() == 0)
337
warning("Found no facets matching domain for boundary condition.");
341
// Iterate over facets
342
Progress p("Computing Dirichlet boundary values, topological search", facets.size());
343
for (uint f = 0; f < facets.size(); f++)
345
// Get cell number and local facet number
346
uint cell_number = facets[f].first;
347
uint facet_number = facets[f].second;
350
Cell cell(_mesh, cell_number);
351
UFCCell ufc_cell(cell);
353
// Interpolate function on cell
354
g.interpolate(data.w, ufc_cell, *data.finite_element, cell, facet_number);
356
// Tabulate dofs on cell
357
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
359
// Tabulate which dofs are on the facet
360
data.dof_map->tabulate_facet_dofs(data.facet_dofs, facet_number);
364
cout << endl << "Handling BC's for:" << endl;
365
cout << "Cell: " << facet.entities(facet.dim() + 1)[0] << endl;
366
cout << "Facet: " << local_facet << endl;
369
// Pick values for facet
370
for (uint i = 0; i < data.dof_map->num_facet_dofs(); i++)
372
const uint dof = data.offset + data.cell_dofs[data.facet_dofs[i]];
373
const real value = data.w[data.facet_dofs[i]];
374
boundary_values[dof] = value;
375
//cout << "Setting BC value: i = " << i << ", dof = " << dof << ", value = " << value << endl;
259
// Get cell to which facet belongs (there may be two, but pick first)
260
Cell cell(_mesh, facet.entities(facet.dim() + 1)[0]);
261
UFCCell ufc_cell(cell);
263
// Get local index of facet with respect to the cell
264
const uint local_facet = cell.index(facet);
266
// Interpolate function on cell
267
g.interpolate(data.w, ufc_cell, *data.finite_element, cell, local_facet);
269
// Tabulate dofs on cell
270
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
272
// Tabulate which dofs are on the facet
273
data.dof_map->tabulate_facet_dofs(data.facet_dofs, local_facet);
277
cout << endl << "Handling BC's for:" << endl;
278
cout << "Cell: " << facet.entities(facet.dim() + 1)[0] << endl;
279
cout << "Facet: " << local_facet << endl;
282
// Pick values for facet
283
for (uint i = 0; i < data.dof_map->num_facet_dofs(); i++)
285
const uint dof = data.offset + data.cell_dofs[data.facet_dofs[i]];
286
const real value = data.w[data.facet_dofs[i]];
287
boundary_values[dof] = value;
288
//cout << "Setting BC value: i = " << i << ", dof = " << dof << ", value = " << value << endl;
381
292
//-----------------------------------------------------------------------------
382
void DirichletBC::computeBCGeometric(std::map<uint, real>& boundary_values,
383
BoundaryCondition::LocalData& data)
293
void DirichletBC::computeBCGeometrical(std::map<uint, real>& boundary_values,
295
BoundaryCondition::LocalData& data)
386
if (facets.size() == 0)
388
warning("Found no facets matching domain for boundary condition.");
392
// Initialize facets, needed for geometric search
393
message("Computing facets, needed for geometric application of boundary conditions.");
394
_mesh.init(_mesh.topology().dim() - 1);
396
// Iterate over facets
397
Progress p("Computing Dirichlet boundary values, geometric search", facets.size());
398
for (uint f = 0; f < facets.size(); f++)
400
// Get cell number and local facet number
401
uint cell_number = facets[f].first;
402
uint facet_number = facets[f].second;
405
Cell cell(_mesh, cell_number);
406
Facet facet(_mesh, cell.entities(_mesh.topology().dim() - 1)[facet_number]);
408
// Loop the vertices associated with the facet
409
for (VertexIterator vertex(facet); !vertex.end(); ++vertex)
297
// Loop the vertices associated with the facet
298
for (VertexIterator vertex(facet); !vertex.end(); ++vertex)
300
// Loop the cells associated with the vertex
301
for (CellIterator c(*vertex); !c.end(); ++c)
411
// Loop the cells associated with the vertex
412
for (CellIterator c(*vertex); !c.end(); ++c)
303
UFCCell ufc_cell(*c);
305
// Interpolate function on cell
306
g.interpolate(data.w, ufc_cell, *data.finite_element, *c);
308
// Tabulate dofs on cell, and their coordinates
309
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
310
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
312
// Loop all dofs on cell
313
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
414
UFCCell ufc_cell(*c);
416
// Interpolate function on cell
417
g.interpolate(data.w, ufc_cell, *data.finite_element, *c);
419
// Tabulate dofs on cell, and their coordinates
420
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
421
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
423
// Loop all dofs on cell
424
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
426
// Check if the coordinates are on current facet and thus on boundary
427
if (!onFacet(data.coordinates[i], facet))
430
// Set boundary value
431
const uint dof = data.offset + data.cell_dofs[i];
432
const real value = data.w[i];
433
boundary_values[dof] = value;
315
// Check if the coordinates are on current facet and thus on boundary
316
if (!onFacet(data.coordinates[i], facet))
319
// Set boundary value
320
const uint dof = data.offset + data.cell_dofs[i];
321
const real value = data.w[i];
322
boundary_values[dof] = value;
439
327
//-----------------------------------------------------------------------------
440
328
void DirichletBC::computeBCPointwise(std::map<uint, real>& boundary_values,
441
BoundaryCondition::LocalData& data)
330
BoundaryCondition::LocalData& data)
443
dolfin_assert(user_sub_domain);
332
UFCCell ufc_cell(cell);
445
// Iterate over cells
446
Progress p("Computing Dirichlet boundary values, pointwise search", facets.size());
447
for (CellIterator cell(_mesh); !cell.end(); ++cell)
334
// Interpolate function on cell
335
g.interpolate(data.w, ufc_cell, *data.finite_element, cell);
337
// Tabulate dofs on cell, and their coordinates
338
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
339
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
341
// Loop all dofs on cell
342
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
449
// Interpolate function on cell
450
UFCCell ufc_cell(*cell);
451
g.interpolate(data.w, ufc_cell, *data.finite_element, *cell);
453
// Tabulate dofs on cell, and their coordinates
454
data.dof_map->tabulate_dofs(data.cell_dofs, ufc_cell);
455
data.dof_map->tabulate_coordinates(data.coordinates, ufc_cell);
457
// Loop all dofs on cell
458
for (uint i = 0; i < data.dof_map->local_dimension(); ++i)
460
// Check if the coordinates are part of the sub domain
461
if ( !user_sub_domain->inside(data.coordinates[i], false) )
464
// Set boundary value
465
const uint dof = data.offset + data.cell_dofs[i];
466
const real value = data.w[i];
467
boundary_values[dof] = value;
344
// Check if the coordinates are part of the sub domain
345
if ( !user_sub_domain->inside(data.coordinates[i], false) )
348
// Set boundary value
349
const uint dof = data.offset + data.cell_dofs[i];
350
const real value = data.w[i];
351
boundary_values[dof] = value;
473
354
//-----------------------------------------------------------------------------
525
406
//-----------------------------------------------------------------------------
407
void DirichletBC::zero(GenericMatrix& A, const Form& form)
409
zero(A, form.dofMaps()[1], form.form());
411
//-----------------------------------------------------------------------------
412
void DirichletBC::zero(GenericMatrix& A, const DofMap& dof_map, const ufc::form& form)
414
// FIXME: How do we reuse the dof map for u?
417
if (method == topological)
418
s = "Applying Dirichlet boundary conditions to linear system";
419
else if (method == geometrical)
420
s = "Applying Dirichlet boundary conditions to linear system (geometrical approach)";
422
s = "Applying Dirichlet boundary conditions to linear system (pointwise approach)";
424
// Make sure we have the facet - cell connectivity
425
const uint D = _mesh.topology().dim();
426
if (method == topological)
427
_mesh.init(D - 1, D);
429
// Create local data for application of boundary conditions
430
BoundaryCondition::LocalData data(form, _mesh, dof_map, sub_system);
432
// A map to hold the mapping from boundary dofs to boundary values
433
std::map<uint, real> boundary_values;
435
if (method == pointwise)
437
Progress p(s, _mesh.size(D));
438
for (CellIterator cell(_mesh); !cell.end(); ++cell)
440
computeBCPointwise(boundary_values, *cell, data);
446
// Iterate over the facets of the mesh
447
Progress p("Applying Dirichlet boundary conditions", _mesh.size(D - 1));
448
for (FacetIterator facet(_mesh); !facet.end(); ++facet)
450
// Skip facets not inside the sub domain
451
if ((*sub_domains)(*facet) != sub_domain)
458
if (method == topological)
459
computeBCTopological(boundary_values, *facet, data);
461
computeBCGeometrical(boundary_values, *facet, data);
468
// Copy boundary value data to arrays
469
uint* dofs = new uint[boundary_values.size()];
470
std::map<uint, real>::const_iterator boundary_value;
472
for (boundary_value = boundary_values.begin(); boundary_value != boundary_values.end(); ++boundary_value)
474
dofs[i++] = boundary_value->first;
477
// Modify linear system (A_ii = 1)
478
A.zero(boundary_values.size(), dofs);
480
// Finalise changes to A
483
// Clear temporary arrays
486
//-----------------------------------------------------------------------------
526
487
void DirichletBC::setSubSystem(SubSystem sub_system)
528
489
this->sub_system = sub_system;