⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 passembler.cpp

📁 利用C
💻 CPP
字号:
// Copyright (C) 2007-2008 Anders Logg.// Licensed under the GNU LGPL Version 2.1.//// Modified by Garth N. Wells, 2007// Modified by Ola Skavhaug, 2007// Modified by Magnus Vikstrøm, 2007//// First added:  2007-01-17// Last changed: 2008-05-28#include <dolfin/log/dolfin_log.h>#include <dolfin/common/Array.h>#include <dolfin/la/GenericTensor.h>#include <dolfin/la/Scalar.h>#include <dolfin/mesh/Mesh.h>#include <dolfin/mesh/Cell.h>#include <dolfin/mesh/Facet.h>#include <dolfin/mesh/BoundaryMesh.h>#include <dolfin/mesh/MeshFunction.h>#include <dolfin/mesh/SubDomain.h>#include <dolfin/mesh/MeshData.h>#include <dolfin/function/Function.h>#include "Form.h"#include "UFC.h"#include "pAssembler.h"#include <dolfin/la/SparsityPattern.h>#include "SparsityPatternBuilder.h"#include "DofMapSet.h"#include <dolfin/main/MPI.h>#include <dolfin/common/timing.h>using namespace dolfin;//-----------------------------------------------------------------------------pAssembler::pAssembler(Mesh& mesh, MeshFunction<uint>& partitions) : mesh(mesh), partitions(&partitions){  // Do nothing}//-----------------------------------------------------------------------------pAssembler::pAssembler(Mesh& mesh) : mesh(mesh){  // Do nothing}//-----------------------------------------------------------------------------pAssembler::~pAssembler(){  // Do nothing}//-----------------------------------------------------------------------------void pAssembler::assemble(GenericTensor& A, Form& form, bool reset_tensor){  form.updateDofMaps(mesh, *partitions);  assemble(A, form.form(), form.coefficients(), form.dofMaps(), 0, 0, 0, reset_tensor);}//-----------------------------------------------------------------------------void pAssembler::assemble(GenericTensor& A, Form& form,                         const SubDomain& sub_domain, bool reset_tensor){  // Extract cell domains  MeshFunction<uint>* cell_domains = 0;  if (form.form().num_cell_integrals() > 0)  {    cell_domains = new MeshFunction<uint>(mesh, mesh.topology().dim());    (*cell_domains) = 1;    sub_domain.mark(*cell_domains, 0);  }  // Extract facet domains  MeshFunction<uint>* facet_domains = 0;  if (form.form().num_exterior_facet_integrals() > 0 ||      form.form().num_interior_facet_integrals() > 0)  {    facet_domains = new MeshFunction<uint>(mesh, mesh.topology().dim() - 1);    (*facet_domains) = 1;    sub_domain.mark(*facet_domains, 0);  }  // Assemble  form.updateDofMaps(mesh, *partitions);  assemble(A, form.form(), form.coefficients(), form.dofMaps(),           cell_domains, facet_domains, facet_domains, reset_tensor);  // Delete domains  if (cell_domains)    delete cell_domains;  if (facet_domains)    delete facet_domains;}//-----------------------------------------------------------------------------void pAssembler::assemble(GenericTensor& A, Form& form,                         const MeshFunction<uint>& cell_domains,                         const MeshFunction<uint>& exterior_facet_domains,                         const MeshFunction<uint>& interior_facet_domains,                         bool reset_tensor){  form.updateDofMaps(mesh, *partitions);  assemble(A, form.form(), form.coefficients(), form.dofMaps(), &cell_domains,            &exterior_facet_domains, &interior_facet_domains, reset_tensor);}//-----------------------------------------------------------------------------dolfin::real pAssembler::assemble(Form& form){  Scalar value;  assemble(value, form);  return value;}//-----------------------------------------------------------------------------dolfin::real pAssembler::assemble(Form& form,                                 const SubDomain& sub_domain){  Scalar value;  assemble(value, form, sub_domain);  return value;}//-----------------------------------------------------------------------------dolfin::real pAssembler::assemble(Form& form,                                 const MeshFunction<uint>& cell_domains,                                 const MeshFunction<uint>& exterior_facet_domains,                                 const MeshFunction<uint>& interior_facet_domains){  Scalar value;  assemble(value, form,           cell_domains, exterior_facet_domains, interior_facet_domains);  return value;}//-----------------------------------------------------------------------------void pAssembler::assemble(GenericTensor& A, const ufc::form& form,                         const Array<Function*>& coefficients,                         const DofMapSet& dof_map_set,                         const MeshFunction<uint>* cell_domains,                         const MeshFunction<uint>* exterior_facet_domains,                         const MeshFunction<uint>* interior_facet_domains,                         bool reset_tensor){  message("Assembling rank %d form.", form.rank());  // Note the importance of treating empty mesh functions as null pointers  // for the PyDOLFIN interface.    // Check arguments  check(form, coefficients);  // Create data structure for local assembly data  UFC ufc(form, mesh, dof_map_set);  // Initialize global tensor  initGlobalTensor(A, dof_map_set, ufc, reset_tensor);  // Assemble over cells  assembleCells(A, coefficients, dof_map_set, ufc, cell_domains);  // Assemble over exterior facets   assembleExteriorFacets(A, coefficients, dof_map_set, ufc, exterior_facet_domains);  // Assemble over interior facets  assembleInteriorFacets(A, coefficients, dof_map_set, ufc, interior_facet_domains);  // Finalise assembly of global tensor  A.apply();}//-----------------------------------------------------------------------------void pAssembler::assembleCells(GenericTensor& A,                              const Array<Function*>& coefficients,                              const DofMapSet& dof_map_set,                              UFC& ufc,                              const MeshFunction<uint>* domains) const{  // Skip assembly if there are no cell integrals  if (ufc.form.num_cell_integrals() == 0)    return;  // Cell integral  ufc::cell_integral* integral = ufc.cell_integrals[0];  // Assemble over cells  message("Assembling over %d cells.", mesh.numCells());  Progress p("Assembling over cells", mesh.numCells());    real t = toc();  printf("pAssembler: start\n");  const uint this_process = MPI::processNumber();  for (CellIterator cell(mesh); !cell.end(); ++cell)  {    // Assemble only cells in this processors partition    if (partitions && (*partitions)(*cell) != this_process)      continue;    // Get integral for sub domain (if any)    if (domains && domains->size() > 0)    {      if (uint domain = (*domains)(*cell) < ufc.form.num_cell_integrals())        integral = ufc.cell_integrals[domain];      else        continue;    }    // Update to current cell    ufc.update(*cell);    // Interpolate coefficients on cell    for (uint i = 0; i < coefficients.size(); i++)      coefficients[i]->interpolate(ufc.w[i], ufc.cell, *ufc.coefficient_elements[i], *cell);        // Tabulate dofs for each dimension    for (uint i = 0; i < ufc.form.rank(); i++)      dof_map_set[i].tabulate_dofs(ufc.dofs[i], ufc.cell, cell->index());    // Tabulate cell tensor    integral->tabulate_tensor(ufc.A, ufc.w, ufc.cell);        // Add entries to global tensor    A.add(ufc.A, ufc.local_dimensions, ufc.dofs);    p++;  }  t = toc() - t;  printf("assembly loop (p): %.3e\n", t);}//-----------------------------------------------------------------------------void pAssembler::assembleExteriorFacets(GenericTensor& A,                                       const Array<Function*>& coefficients,                                       const DofMapSet& dof_map_set,                                       UFC& ufc,                                       const MeshFunction<uint>* domains) const{  // Skip assembly if there are no exterior facet integrals  if (ufc.form.num_exterior_facet_integrals() == 0)    return;    // Exterior facet integral  ufc::exterior_facet_integral* integral = ufc.exterior_facet_integrals[0];  // Create boundary mesh  BoundaryMesh boundary(mesh);  MeshFunction<uint>* cell_map = boundary.data().meshFunction("cell map");  dolfin_assert(cell_map);    // Assemble over exterior facets (the cells of the boundary)  message("Assembling over %d exterior facets.", boundary.numCells());  Progress p("Assembling over exterior facets", boundary.numCells());  for (CellIterator boundary_cell(boundary); !boundary_cell.end(); ++boundary_cell)  {    // Get mesh facet corresponding to boundary cell    Facet mesh_facet(mesh, (*cell_map)(*boundary_cell));    // Get integral for sub domain (if any)    if (domains && domains->size() > 0)    {      if (uint domain = (*domains)(mesh_facet) < ufc.form.num_exterior_facet_integrals())        integral = ufc.exterior_facet_integrals[domain];      else        continue;    }    // Get mesh cell to which mesh facet belongs (pick first, there is only one)    dolfin_assert(mesh_facet.numEntities(mesh.topology().dim()) == 1);    Cell mesh_cell(mesh, mesh_facet.entities(mesh.topology().dim())[0]);    // Get local index of facet with respect to the cell    const uint local_facet = mesh_cell.index(mesh_facet);          // Update to current cell    ufc.update(mesh_cell);    // Interpolate coefficients on cell    for (uint i = 0; i < coefficients.size(); i++)      coefficients[i]->interpolate(ufc.w[i], ufc.cell, *ufc.coefficient_elements[i], mesh_cell, local_facet);    // Tabulate dofs for each dimension    for (uint i = 0; i < ufc.form.rank(); i++)      dof_map_set[i].tabulate_dofs(ufc.dofs[i], ufc.cell, mesh_cell.index());    // Tabulate exterior facet tensor    ufc.exterior_facet_integrals[0]->tabulate_tensor(ufc.A, ufc.w, ufc.cell, local_facet);    // Add entries to global tensor    A.add(ufc.A, ufc.local_dimensions, ufc.dofs);    p++;    }}//-----------------------------------------------------------------------------void pAssembler::assembleInteriorFacets(GenericTensor& A,                                       const Array<Function*>& coefficients,                                       const DofMapSet& dof_map_set,                                       UFC& ufc,                                       const MeshFunction<uint>* domains) const{  // Skip assembly if there are no interior facet integrals  if (ufc.form.num_interior_facet_integrals() == 0)    return;    // Interior facet integral  ufc::interior_facet_integral* integral = ufc.interior_facet_integrals[0];  // Compute facets and facet - cell connectivity if not already computed  mesh.init(mesh.topology().dim() - 1);  mesh.init(mesh.topology().dim() - 1, mesh.topology().dim());  mesh.order();    // Assemble over interior facets (the facets of the mesh)  message("Assembling over %d interior facets.", mesh.numFacets());  Progress p("Assembling over interior facets", mesh.numFacets());  for (FacetIterator facet(mesh); !facet.end(); ++facet)  {    // Check if we have an interior facet    if ( facet->numEntities(mesh.topology().dim()) != 2 )    {      p++;      continue;    }    // Get integral for sub domain (if any)    if (domains && domains->size() > 0)    {      if (uint domain = (*domains)(*facet) < ufc.form.num_interior_facet_integrals())        integral = ufc.interior_facet_integrals[domain];      else        continue;    }    // Get cells incident with facet    Cell cell0(mesh, facet->entities(mesh.topology().dim())[0]);    Cell cell1(mesh, facet->entities(mesh.topology().dim())[1]);          // Get local index of facet with respect to each cell    uint facet0 = cell0.index(*facet);    uint facet1 = cell1.index(*facet);    // Update to current pair of cells    ufc.update(cell0, cell1);        // Interpolate coefficients on cell    for (uint i = 0; i < coefficients.size(); i++)    {      const uint offset = ufc.coefficient_elements[i]->space_dimension();      coefficients[i]->interpolate(ufc.macro_w[i], ufc.cell0, *ufc.coefficient_elements[i], cell0, facet0);      coefficients[i]->interpolate(ufc.macro_w[i] + offset, ufc.cell1, *ufc.coefficient_elements[i], cell1, facet1);    }    // Tabulate dofs for each dimension on macro element    for (uint i = 0; i < ufc.form.rank(); i++)    {      const uint offset = ufc.local_dimensions[i];      dof_map_set[i].tabulate_dofs(ufc.macro_dofs[i], ufc.cell0, cell0.index());      dof_map_set[i].tabulate_dofs(ufc.macro_dofs[i] + offset, ufc.cell1, cell1.index());    }    // Tabulate exterior interior facet tensor on macro element    ufc.interior_facet_integrals[0]->tabulate_tensor(ufc.macro_A, ufc.macro_w, ufc.cell0, ufc.cell1, facet0, facet1);    // Add entries to global tensor    A.add(ufc.macro_A, ufc.macro_local_dimensions, ufc.macro_dofs);    p++;  }}//-----------------------------------------------------------------------------void pAssembler::check(const ufc::form& form,                      const Array<Function*>& coefficients) const{  // Check that we get the correct number of coefficients  if ( coefficients.size() != form.num_coefficients() )    error("Incorrect number of coefficients for form: %d given but %d required.",                  coefficients.size(), form.num_coefficients());}//-----------------------------------------------------------------------------void pAssembler::initGlobalTensor(GenericTensor& A, const DofMapSet& dof_map_set, UFC& ufc,                                 bool reset_tensor) const{  if (reset_tensor)  {    // Build parallel dof map    dof_map_set.build(ufc);        // Build sparsity pattern from dof map    GenericSparsityPattern* sparsity_pattern = A.factory().createPattern();     SparsityPatternBuilder::build(*sparsity_pattern, mesh, ufc, dof_map_set);    A.init(*sparsity_pattern);    delete sparsity_pattern;  }  else    A.zero();}//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -