Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
14450 commits behind the upstream repository.
dgAlgorithm.cpp 6.54 KiB
#include <set>
#include "dgAlgorithm.h"
#include "dgGroupOfElements.h"
#include "dgSystemOfEquations.h"
#include "dgConservationLaw.h"
#include "GEntity.h"
#include "MElement.h"
#include "GModel.h"
#include "MEdge.h"
#include "function.h"
#include "dgLimiter.h"
#include "dgTransformNodalValue.h"
#include "meshPartition.h"

// works for any number of groups 

/*
void dgAlgorithm::residualForSomeGroups( const dgConservationLaw &claw,
          std::vector<dgGroupOfElements *>groups,
          dgGroupCollection &groupCollection,
          dgDofContainer &solution,
          dgDofContainer &residu)
{
  solution.scatter();
  int nbFields=claw.getNbFields();
  //volume term
  std::set<dgGroupOfFaces *>groupOfInternalFacesToUpdate;
  std::vector<dgGroupOfFaces *>groupOfBoundaryFacesToUpdate;
  for(size_t i=0;i<groups.size() ; i++) {
    int groupId=groups[i]->getId();
    residu.getGroupProxy(groupId).scale(0);
    residualVolume(claw,*groups[i],solution.getGroupProxy(groupId),residu.getGroupProxy(groupId));
    groupOfInternalFacesToUpdate.insert(groups[i]->getGroupsOfNeighboringFaces()->begin(),groups[i]->getGroupsOfNeighboringFaces()->end());
    groupOfBoundaryFacesToUpdate.insert(groupOfBoundaryFacesToUpdate.end(),groups[i]->getGroupsOfBoundaryFaces()->begin(),groups[i]->getGroupsOfBoundaryFaces()->end());
    groupOfInternalFacesToUpdate.insert(groups[i]->getGroupOfInsideFaces());
  }
  for(std::set<dgGroupOfFaces *>::iterator it=groupOfInternalFacesToUpdate.begin();it!=groupOfInternalFacesToUpdate.end();it++) {
    dgGroupOfFaces *faces = *it;
    int iGroupLeft = -1, iGroupRight = -1;
    for(size_t j=0;j<groupCollection.getNbElementGroups(); j++) {
      dgGroupOfElements *groupj = groupCollection.getElementGroup(j);
      if (groupj == &faces->getGroupLeft()) iGroupLeft = j;
      if (groupj == &faces->getGroupRight()) iGroupRight= j;
    }
    for(size_t j=0;j<groupCollection.getNbGhostGroups(); j++) {
      dgGroupOfElements *groupj = groupCollection.getGhostGroup(j);
      if (groupj == &faces->getGroupLeft()) iGroupLeft = j;
      if (groupj == &faces->getGroupLeft())iGroupLeft = j + groupCollection.getNbElementGroups();
      if (groupj == &faces->getGroupRight())iGroupRight= j + groupCollection.getNbElementGroups();
    }
    fullMatrix<double> solInterface(faces->getNbNodes(),faces->getNbElements()*2*nbFields);
    fullMatrix<double> residuInterface(faces->getNbNodes(),faces->getNbElements()*2*nbFields);
    faces->mapToInterface(nbFields, solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight), solInterface);
    residualInterface(claw,*faces,solInterface,solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight),residuInterface);
    faces->mapFromInterface(nbFields, residuInterface,residu.getGroupProxy(iGroupLeft), residu.getGroupProxy(iGroupRight));
  }
  //boundaries
  for(size_t i=0;i<groupOfBoundaryFacesToUpdate.size() ; i++) {
    dgGroupOfFaces *faces = groupOfBoundaryFacesToUpdate[i];
    int iGroupLeft = -1, iGroupRight = -1;
    for(size_t j=0;j<groupCollection.getNbElementGroups(); j++) {
      dgGroupOfElements *groupj = groupCollection.getElementGroup(j);
      if (groupj == &faces->getGroupLeft())iGroupLeft = j;
      if (groupj == &faces->getGroupRight())iGroupRight= j;
    }
    fullMatrix<double> solInterface(faces->getNbNodes(),faces->getNbElements()*nbFields);
    fullMatrix<double> residuInterface(faces->getNbNodes(),faces->getNbElements()*nbFields);
    faces->mapToInterface(nbFields, solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight), solInterface);
    residualBoundary(claw,*faces,solInterface,solution.getGroupProxy(iGroupLeft),residuInterface);
    faces->mapFromInterface(nbFields, residuInterface, residu.getGroupProxy(iGroupLeft), residu.getGroupProxy(iGroupRight));
  }
}
*/

void dgAlgorithm::computeElementaryTimeSteps ( //dofManager &dof, // the DOF manager (maybe useless here)
                                              const dgConservationLaw &claw,   // the conservation law
                                              const dgGroupOfElements & group, 
                                              fullMatrix<double> &solution,
                                              std::vector<double> & DT
                                               )
{ 
  const int nbFields = claw.getNbFields();
  dataCacheMap cacheMap;
  cacheMap.setNbEvaluationPoints(group.getNbIntegrationPoints());
  dataCacheDouble &sol = cacheMap.provideSolution(nbFields);
  dataCacheDouble &UVW = cacheMap.provideParametricCoordinates();
  UVW.set(group.getIntegrationPointsMatrix());
  // provided dataCache
  dataCacheDouble *maxConvectiveSpeed = claw.newMaxConvectiveSpeed(cacheMap);
  dataCacheDouble *maximumDiffusivity = claw.newMaximumDiffusivity(cacheMap);
        
  /* This is an estimate on how lengths changes with p 
     It is merely the smallest distance between gauss 
     points at order p + 1 */
  const double p   = group.getOrder();
  const double Cip = 3 * (p + 1) * (p + group.getDimUVW()) ;
  double l_red = 1./3.*p*p +7./6.*p +1.0;
  double l_red_sq = l_red*l_red;
  DT.resize(group.getNbElements());
  for (int iElement=0 ; iElement<group.getNbElements() ;++iElement) {
    sol.setAsProxy(solution, iElement*nbFields, nbFields);
    cacheMap.setElement(group.getElement(iElement));
    const double L = group.getInnerRadius(iElement);
    double spectralRadius = 0.0;
    if (maximumDiffusivity){
      double nu = (*maximumDiffusivity)(0,0);
      for (int k=1;k<group.getNbNodes();k++) nu = std::max((*maximumDiffusivity)(k,0), nu);
      spectralRadius +=  group.getDimUVW()*nu/(L*L)*std::max(l_red_sq,6.*l_red*Cip);
      spectralRadius +=  4.0*nu*l_red*Cip/(L*L);
    }
    if (maxConvectiveSpeed){
      double c = (*maxConvectiveSpeed)(0,0);
      for (int k=1;k<group.getNbNodes();k++) c = std::max((*maxConvectiveSpeed)(k,0), c);
      spectralRadius += 4.0*c*l_red/L; 
    }
    DT[iElement] = 1./spectralRadius;
  }
}

void dgAlgorithm::multAddInverseMassMatrix ( /*dofManager &dof,*/
                                            const dgGroupOfElements & group,
                                            fullMatrix<double> &residu,
                                            fullMatrix<double> &sol)
{
  fullMatrix<double> residuEl;
  fullMatrix<double> solEl;
  fullMatrix<double> iMassEl;
  int nFields=sol.size2()/group.getNbElements();
  for(int i=0;i<group.getNbElements();i++) {
    residuEl.setAsProxy(residu,i*nFields,nFields);
    solEl.setAsProxy(sol,i*nFields,nFields);
    iMassEl.setAsProxy(group.getInverseMassMatrix(),i*group.getNbNodes(),group.getNbNodes());
    solEl.gemm(iMassEl,residuEl);
  }
}