From 0331692962e642c3260f162277f49d34e2b4125b Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Tue, 28 Feb 2006 09:53:13 +0000 Subject: [PATCH] The old assembler for planar rods [[Imported from SVN: r738]] --- src/planarrodassembler.cc | 476 ++++++++++++++++++++++++++++++++++++++ src/planarrodassembler.hh | 91 ++++++++ 2 files changed, 567 insertions(+) create mode 100644 src/planarrodassembler.cc create mode 100644 src/planarrodassembler.hh diff --git a/src/planarrodassembler.cc b/src/planarrodassembler.cc new file mode 100644 index 00000000..de20dda1 --- /dev/null +++ b/src/planarrodassembler.cc @@ -0,0 +1,476 @@ +#include <dune/istl/bcrsmatrix.hh> +#include <dune/common/fmatrix.hh> +#include <dune/istl/matrixindexset.hh> +#include <dune/common/matrix.hh> + +#include <dune/quadrature/quadraturerules.hh> + +#include <dune/disc/shapefunctions/lagrangeshapefunctions.hh> + +template <class GridType, int polOrd> +void Dune::RodAssembler<GridType, polOrd>:: +getNeighborsPerVertex(MatrixIndexSet& nb) const +{ + const int gridDim = GridType::dimension; + const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(grid_->maxLevel()); + + int i, j; + int n = grid_->size(grid_->maxLevel(), gridDim); + + nb.resize(n, n); + + ElementIterator it = grid_->template lbegin<0>( grid_->maxLevel() ); + ElementIterator endit = grid_->template lend<0> ( grid_->maxLevel() ); + + for (; it!=endit; ++it) { + + for (i=0; i<it->template count<gridDim>(); i++) { + + for (j=0; j<it->template count<gridDim>(); j++) { + + //int iIdx = it->template subIndex<gridDim>(i); + //int jIdx = it->template subIndex<gridDim>(j); + int iIdx = indexSet.template subIndex<gridDim>(*it,i); + int jIdx = indexSet.template subIndex<gridDim>(*it,j); + + nb.add(iIdx, jIdx); + + } + + } + + } + +} + +template <class GridType, int polOrd> +void Dune::RodAssembler<GridType, polOrd>:: +assembleMatrix(const BlockVector<FieldVector<double, blocksize> >& sol, + BCRSMatrix<MatrixBlock>& matrix) +{ + const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(grid_->maxLevel()); + + MatrixIndexSet neighborsPerVertex; + getNeighborsPerVertex(neighborsPerVertex); + + matrix = 0; + + ElementIterator it = grid_->template lbegin<0>( grid_->maxLevel() ); + ElementIterator endit = grid_->template lend<0> ( grid_->maxLevel() ); + + Matrix<MatrixBlock> mat; + + for( ; it != endit; ++it ) { + + //const BaseFunctionSetType & baseSet = functionSpace_.getBaseFunctionSet( *it ); + const LagrangeShapeFunctionSet<double, double, gridDim> & baseSet + = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(it->geometry().type(), elementOrder); + const int numOfBaseFct = baseSet.size(); + + mat.resize(numOfBaseFct, numOfBaseFct); + + // Extract local solution + BlockVector<FieldVector<double, blocksize> > localSolution(numOfBaseFct); + + for (int i=0; i<numOfBaseFct; i++) + //localSolution[i] = sol[functionSpace_.mapToGlobal(*it,i)]; + localSolution[i] = sol[indexSet.template subIndex<gridDim>(*it,i)]; + + // setup matrix + getLocalMatrix( *it, localSolution, numOfBaseFct, mat); + + // Add element matrix to global stiffness matrix + for(int i=0; i<numOfBaseFct; i++) { + + //int row = functionSpace_.mapToGlobal( *it , i ); + int row = indexSet.template subIndex<gridDim>(*it,i); + + for (int j=0; j<numOfBaseFct; j++ ) { + + //int col = functionSpace_.mapToGlobal( *it , j ); + int col = indexSet.template subIndex<gridDim>(*it,j); + matrix[row][col] += mat[i][j]; + + } + } + + } + +} + + + + + + +template <class GridType, int polOrd> +template <class MatrixType> +void Dune::RodAssembler<GridType, polOrd>:: +getLocalMatrix( EntityType &entity, + const BlockVector<FieldVector<double, blocksize> >& localSolution, + const int matSize, MatrixType& localMat) const +{ + const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(grid_->maxLevel()); + + /* ndof is the number of vectors of the element */ + int ndof = matSize; + + for (int i=0; i<matSize; i++) + for (int j=0; j<matSize; j++) + localMat[i][j] = 0; + + //const BaseFunctionSetType & baseSet = this->functionSpace_.getBaseFunctionSet( entity ); + const LagrangeShapeFunctionSet<double, double, gridDim> & baseSet + = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(entity.geometry().type(), elementOrder); + + // Get quadrature rule + const QuadratureRule<double, gridDim>& quad = QuadratureRules<double, gridDim>::rule(entity.geometry().type(), polOrd); + + /* Loop over all integration points */ + for (int ip=0; ip<quad.size(); ip++) { + + // Local position of the quadrature point + const FieldVector<double,gridDim>& quadPos = quad[ip].position(); + + // calc Jacobian inverse before integration element is evaluated + const FieldMatrix<double,gridDim,gridDim>& inv = entity.geometry().jacobianInverseTransposed(quadPos); + const double integrationElement = entity.geometry().integrationElement(quadPos); + + /* Compute the weight of the current integration point */ + double weight = quad[ip].weight() * integrationElement; + + /**********************************************/ + /* compute gradients of the shape functions */ + /**********************************************/ + Array<FieldVector<double,gridDim> > shapeGrad(ndof); + + for (int dof=0; dof<ndof; dof++) { + + //baseSet.jacobian(dof, quadPos, shapeGrad[dof]); + for (int i=0; i<gridDim; i++) + shapeGrad[dof][i] = baseSet[dof].evaluateDerivative(0,i,quadPos); + + // multiply with jacobian inverse + FieldVector<double,gridDim> tmp(0); + inv.umv(shapeGrad[dof], tmp); + shapeGrad[dof] = tmp; + + } + + + double shapeFunction[matSize]; + for(int i=0; i<matSize; i++) + //baseSet.eval(i,quadPos,shapeFunction[i]); + shapeFunction[i] = baseSet[i].evaluateFunction(0,quadPos); + + // ////////////////////////////////// + // Interpolate + // ////////////////////////////////// + + double x_s = localSolution[0][0]*shapeGrad[0][0] + localSolution[1][0]*shapeGrad[1][0]; + double y_s = localSolution[0][1]*shapeGrad[0][0] + localSolution[1][1]*shapeGrad[1][0]; + + double theta = localSolution[0][2]*shapeFunction[0] + localSolution[1][2]*shapeFunction[1]; + + for (int i=0; i<matSize; i++) { + + for (int j=0; j<matSize; j++) { + + // \partial J^2 / \partial x_i \partial x_j + localMat[i][j][0][0] += weight * shapeGrad[i][0] * shapeGrad[j][0] + * (A1 * cos(theta) * cos(theta) + A3 * sin(theta) * sin(theta)); + + // \partial J^2 / \partial x_i \partial y_j + localMat[i][j][0][1] += weight * shapeGrad[i][0] * shapeGrad[j][0] + * (-A1 + A3) * sin(theta)* cos(theta); + + // \partial J^2 / \partial x_i \partial theta_j + localMat[i][j][0][2] += weight * shapeGrad[i][0] * shapeFunction[j] + * (-A1 * (x_s*sin(theta) + y_s*cos(theta)) * cos(theta) + - A1* (x_s*cos(theta) - y_s*sin(theta)) * sin(theta) + +A3 * (x_s*cos(theta) - y_s*sin(theta)) * sin(theta) + +A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * cos(theta)); + + // \partial J^2 / \partial y_i \partial x_j + localMat[i][j][1][0] += weight * shapeGrad[i][0] * shapeGrad[j][0] + * (-A1 * sin(theta)* cos(theta) + A3 * cos(theta) * sin(theta)); + + // \partial J^2 / \partial y_i \partial y_j + localMat[i][j][1][1] += weight * shapeGrad[i][0] * shapeGrad[j][0] + * (A1 * sin(theta)*sin(theta) + A3 * cos(theta)*cos(theta)); + + // \partial J^2 / \partial y_i \partial theta_j + localMat[i][j][1][2] += weight * shapeGrad[i][0] * shapeFunction[j] + * (A1 * (x_s * sin(theta) + y_s * cos(theta)) * sin(theta) + -A1 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta) + +A3 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta) + -A3 * (x_s * sin(theta) + y_s * cos(theta) - 1) * sin(theta)); + + // \partial J^2 / \partial theta_i \partial x_j + localMat[i][j][2][0] += weight * shapeFunction[i] * shapeGrad[j][0] + * (-A1 * (x_s*sin(theta) + y_s*cos(theta)) * cos(theta) + - A1* (x_s*cos(theta) - y_s*sin(theta)) * sin(theta) + +A3 * (x_s*cos(theta) - y_s*sin(theta)) * sin(theta) + +A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * cos(theta)); + + // \partial J^2 / \partial theta_i \partial y_j + localMat[i][j][2][1] += weight * shapeFunction[i] * shapeGrad[j][0] + * (A1 * (x_s * sin(theta) + y_s * cos(theta)) * sin(theta) + -A1 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta) + +A3 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta) + -A3 * (x_s * sin(theta) + y_s * cos(theta) - 1) * sin(theta)); + + // \partial J^2 / \partial theta_i \partial theta_j + localMat[i][j][2][2] += weight * B * shapeGrad[i][0] * shapeGrad[j][0]; + localMat[i][j][2][2] += weight * shapeFunction[i] * shapeFunction[j] + * (+ A1 * (x_s*sin(theta) + y_s*cos(theta)) * (x_s*sin(theta) + y_s*cos(theta)) + + A1 * (x_s*cos(theta) - y_s*sin(theta)) * (-x_s*cos(theta)+ y_s*sin(theta)) + + A3 * (x_s*cos(theta) - y_s*sin(theta)) * (x_s*cos(theta) - y_s*sin(theta)) + - A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * (x_s*sin(theta) + y_s*cos(theta))); + + + + } + + } + + + } + +#if 0 + static int eleme = 0; + printf("********* Element %d **********\n", eleme++); + for (int row=0; row<matSize; row++) { + + for (int rcomp=0; rcomp<dim; rcomp++) { + + for (int col=0; col<matSize; col++) { + + for (int ccomp=0; ccomp<dim; ccomp++) + std::cout << mat[row][col][rcomp][ccomp] << " "; + + std::cout << " "; + + } + + std::cout << std::endl; + + } + + std::cout << std::endl; + + } + exit(0); +#endif + +} + +template <class GridType, int polOrd> +void Dune::RodAssembler<GridType, polOrd>:: +assembleGradient(const BlockVector<FieldVector<double, blocksize> >& sol, + BlockVector<FieldVector<double, blocksize> >& grad) const +{ + const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(grid_->maxLevel()); + const int maxlevel = grid_->maxLevel(); + + if (sol.size()!=grid_->size(maxlevel, gridDim)) + DUNE_THROW(Exception, "Solution vector doesn't match the grid!"); + + grad.resize(sol.size()); + grad = 0; + + ElementIterator it = grid_->template lbegin<0>(maxlevel); + ElementIterator endIt = grid_->template lend<0>(maxlevel); + + // Loop over all elements + for (; it!=endIt; ++it) { + + // Extract local solution on this element + const LagrangeShapeFunctionSet<double, double, gridDim> & baseSet + = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(it->geometry().type(), elementOrder); + const int numOfBaseFct = baseSet.size(); + + FieldVector<double, blocksize> localSolution[numOfBaseFct]; + + for (int i=0; i<numOfBaseFct; i++) + localSolution[i] = sol[indexSet.template subIndex<gridDim>(*it,i)]; + + // Get quadrature rule + const QuadratureRule<double, gridDim>& quad = QuadratureRules<double, gridDim>::rule(it->geometry().type(), polOrd); + + for (int pt=0; pt<quad.size(); pt++) { + + // Local position of the quadrature point + const FieldVector<double,gridDim>& quadPos = quad[pt].position(); + + const FieldMatrix<double,1,1>& inv = it->geometry().jacobianInverseTransposed(quadPos); + const double integrationElement = it->geometry().integrationElement(quadPos); + + double weight = quad[pt].weight() * integrationElement; + + // /////////////////////////////////////// + // Compute deformation gradient + // /////////////////////////////////////// + Array<FieldVector<double,gridDim> > shapeGrad(numOfBaseFct); + + for (int dof=0; dof<numOfBaseFct; dof++) { + + for (int i=0; i<gridDim; i++) + shapeGrad[dof][i] = baseSet[dof].evaluateDerivative(0,i,quadPos); + + // multiply with jacobian inverse + FieldVector<double,gridDim> tmp(0); + inv.umv(shapeGrad[dof], tmp); + shapeGrad[dof] = tmp; + + } + + // Get the value of the shape functions + double shapeFunction[2]; + for(int i=0; i<2; i++) + shapeFunction[i] = baseSet[i].evaluateFunction(0,quadPos); + + // ////////////////////////////////// + // Interpolate + // ////////////////////////////////// + + double x_s = localSolution[0][0]*shapeGrad[0][0] + localSolution[1][0]*shapeGrad[1][0]; + double y_s = localSolution[0][1]*shapeGrad[0][0] + localSolution[1][1]*shapeGrad[1][0]; + double theta_s = localSolution[0][2]*shapeGrad[0][0] + localSolution[1][2]*shapeGrad[1][0]; + + double theta = localSolution[0][2]*shapeFunction[0] + localSolution[1][2]*shapeFunction[1]; + + // ///////////////////////////////////////////// + // Sum it all up + // ///////////////////////////////////////////// + + double partA1 = A1 * (x_s * cos(theta) - y_s * sin(theta)); + double partA3 = A3 * (x_s * sin(theta) + y_s * cos(theta) - 1); + + for (int dof=0; dof<numOfBaseFct; dof++) { + + int globalDof = indexSet.template subIndex<gridDim>(*it,dof); + + //printf("globalDof: %d partA1: %g partA3: %g\n", globalDof, partA1, partA3); + + // \partial J / \partial x^i + grad[globalDof][0] += weight * (partA1 * cos(theta) + partA3 * sin(theta)) * shapeGrad[dof][0]; + + // \partial J / \partial y^i + grad[globalDof][1] += weight * (-partA1 * sin(theta) + partA3 * cos(theta)) * shapeGrad[dof][0]; + + // \partial J / \partial \theta^i + grad[globalDof][2] += weight * (B * theta_s * shapeGrad[dof][0] + + partA1 * (-x_s * sin(theta) - y_s * cos(theta)) * shapeFunction[dof] + + partA3 * ( x_s * cos(theta) - y_s * sin(theta)) * shapeFunction[dof]); + + } + + + } + + } + +} + + +template <class GridType, int polOrd> +double Dune::RodAssembler<GridType, polOrd>:: +computeEnergy(const BlockVector<FieldVector<double, blocksize> >& sol) const +{ + const int maxlevel = grid_->maxLevel(); + double energy = 0; + + const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(maxlevel); + + if (sol.size()!=grid_->size(maxlevel, gridDim)) + DUNE_THROW(Exception, "Solution vector doesn't match the grid!"); + + ElementIterator it = grid_->template lbegin<0>(maxlevel); + ElementIterator endIt = grid_->template lend<0>(maxlevel); + + // Loop over all elements + for (; it!=endIt; ++it) { + + // Extract local solution on this element + // const BaseFunctionSetType & baseSet = functionSpace_.getBaseFunctionSet( *it ); +// const int numOfBaseFct = baseSet.getNumberOfBaseFunctions(); + const LagrangeShapeFunctionSet<double, double, gridDim> & baseSet + = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(it->geometry().type(), elementOrder); + int numOfBaseFct = baseSet.size(); + + FieldVector<double, blocksize> localSolution[numOfBaseFct]; + + for (int i=0; i<numOfBaseFct; i++) + //localSolution[i] = sol[functionSpace_.mapToGlobal(*it,i)]; + localSolution[i] = sol[indexSet.template subIndex<gridDim>(*it,i)]; + + // Get quadrature rule + const QuadratureRule<double, gridDim>& quad = QuadratureRules<double, gridDim>::rule(it->geometry().type(), polOrd); + + for (int pt=0; pt<quad.size(); pt++) { + + // Local position of the quadrature point + const FieldVector<double,gridDim>& quadPos = quad[pt].position(); + + const FieldMatrix<double,1,1>& inv = it->geometry().jacobianInverseTransposed(quadPos); + const double integrationElement = it->geometry().integrationElement(quadPos); + + double weight = quad[pt].weight() * integrationElement; + + // /////////////////////////////////////// + // Compute deformation gradient + // /////////////////////////////////////// + Array<FieldVector<double,gridDim> > shapeGrad(numOfBaseFct); + + for (int dof=0; dof<numOfBaseFct; dof++) { + + //baseSet.jacobian(dof, quadPos, shapeGrad[dof]); + for (int i=0; i<gridDim; i++) + shapeGrad[dof][i] = baseSet[dof].evaluateDerivative(0,i,quadPos); + //std::cout << "Gradient " << dof << ": " << shape_grads[dof] << std::endl; + + // multiply with jacobian inverse + FieldVector<double,gridDim> tmp(0); + inv.umv(shapeGrad[dof], tmp); + shapeGrad[dof] = tmp; + //std::cout << "Gradient " << dof << ": " << shape_grads[dof] << std::endl; + + + + } + + // Get the value of the shape functions + double shapeFunction[2]; + for(int i=0; i<2; i++) + shapeFunction[i] = baseSet[i].evaluateFunction(0,quadPos); + + // ////////////////////////////////// + // Interpolate + // ////////////////////////////////// + + double x_s = localSolution[0][0]*shapeGrad[0][0] + localSolution[1][0]*shapeGrad[1][0]; + double y_s = localSolution[0][1]*shapeGrad[0][0] + localSolution[1][1]*shapeGrad[1][0]; + double theta_s = localSolution[0][2]*shapeGrad[0][0] + localSolution[1][2]*shapeGrad[1][0]; + + double theta = localSolution[0][2]*shapeFunction[0] + localSolution[1][2]*shapeFunction[1]; + + // ///////////////////////////////////////////// + // Sum it all up + // ///////////////////////////////////////////// + + double partA1 = x_s * cos(theta) - y_s * sin(theta); + double partA3 = x_s * sin(theta) + y_s * cos(theta) - 1; + + + energy += 0.5 * weight * (B * theta_s * theta_s + + A1 * partA1 * partA1 + + A3 * partA3 * partA3); + + } + + } + + return energy; + +} diff --git a/src/planarrodassembler.hh b/src/planarrodassembler.hh new file mode 100644 index 00000000..452697b4 --- /dev/null +++ b/src/planarrodassembler.hh @@ -0,0 +1,91 @@ +#ifndef DUNE_PLANAR_ROD_ASSEMBLER_HH +#define DUNE_PLANAR_ROD_ASSEMBLER_HH + +#include <dune/istl/bcrsmatrix.hh> +#include <dune/common/fmatrix.hh> +#include <dune/istl/matrixindexset.hh> +#include <dune/common/matrix.hh> + +namespace Dune +{ + + /** \brief The FEM operator for an extensible, shearable rod + */ + template <class GridType, int polOrd> + class PlanarRodAssembler { + + typedef typename GridType::template Codim<0>::Entity EntityType; + typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; + + //! Dimension of the grid. This needs to be one! + enum { gridDim = GridType::dimension }; + + enum { elementOrder = 1}; + + //! Each block is x, y, theta + enum { blocksize = 3 }; + + //! + typedef FieldMatrix<double, blocksize, blocksize> MatrixBlock; + + const GridType* grid_; + + /** \brief Material constants */ + double B; + double A1; + double A3; + + public: + + //! ??? + RodAssembler(const GridType &grid) : + grid_(&grid) + { + B = 1; + A1 = 1; + A3 = 1; + } + + ~RodAssembler() {} + + void setParameters(double b, double a1, double a3) { + B = b; + A1 = a1; + A3 = a3; + } + + /** \brief Assemble the tangent stiffness matrix and the right hand side + */ + void assembleMatrix(const BlockVector<FieldVector<double, blocksize> >& sol, + BCRSMatrix<MatrixBlock>& matrix); + + void assembleGradient(const BlockVector<FieldVector<double, blocksize> >& sol, + BlockVector<FieldVector<double, blocksize> >& grad) const; + + /** \brief Compute the energy of a deformation state */ + double computeEnergy(const BlockVector<FieldVector<double, blocksize> >& sol) const; + + void getNeighborsPerVertex(MatrixIndexSet& nb) const; + + protected: + + /** \brief Compute the element tangent stiffness matrix */ + template <class MatrixType> + void getLocalMatrix( EntityType &entity, + const BlockVector<FieldVector<double, blocksize> >& localSolution, + const int matSize, MatrixType& mat) const; + + + + + + + + }; // end class + +} // end namespace + +#include "planarrodassembler.cc" + +#endif + -- GitLab