Ejemplo n.º 1
0
void ReturnByRef::apply()
{
  RefMap           map;
  RefMap::iterator iter;
  FnSet            asgnUpdates;

  returnByRefCollectCalls(map, asgnUpdates);

  for (iter = map.begin(); iter != map.end(); iter++)
    iter->second->transform();

  for_set(FnSymbol, fn, asgnUpdates)
    updateAssignments(fn);

  for (int i = 0; i < virtualMethodTable.n; i++)
  {
    if (virtualMethodTable.v[i].key)
    {
      int  numFns = virtualMethodTable.v[i].value->n;

      for (int j = 0; j < numFns; j++)
      {
        FnSymbol* fn = virtualMethodTable.v[i].value->v[j];
        TransformationKind tfKind = transformableFunctionKind(fn);

        if (tfKind == TF_FULL)
          transformFunction(fn);
        else if (tfKind == TF_ASGN)
          updateAssignments(fn);
      }
    }
  }
}
Ejemplo n.º 2
0
// Custom function to calculate drag coefficient.
double integrate_over_wall(MeshFunction* meshfn, int marker)
{
  Quad2D* quad = &g_quad_2d_std;
  meshfn->set_quad_2d(quad);

  double integral = 0.0;
  Element* e;
  Mesh* mesh = meshfn->get_mesh();

  for_all_active_elements(e, mesh)
  {
    for(int edge = 0; edge < e->nvert; edge++)
    {
      if ((e->en[edge]->bnd) && (e->en[edge]->marker == marker))
      {
        update_limit_table(e->get_mode());
        RefMap* ru = meshfn->get_refmap();

        meshfn->set_active_element(e);
        int eo = quad->get_edge_points(edge);
        meshfn->set_quad_order(eo, H2D_FN_VAL);
        scalar *uval = meshfn->get_fn_values();
        double3* pt = quad->get_points(eo);
        double3* tan = ru->get_tangent(edge);
        for (int i = 0; i < quad->get_num_points(eo); i++)
          integral += pt[i][2] * uval[i] * tan[i][2];
      }
    }
  }
  return integral * 0.5;
}
Ejemplo n.º 3
0
void ReturnByRef::returnByRefCollectCalls(RefMap& calls)
{
  RefMap::iterator iter;

  forv_Vec(CallExpr, call, gCallExprs)
  {
    if (FnSymbol* fn = theTransformableFunction(call))
    {
      RefMap::iterator iter = calls.find(fn->id);
      ReturnByRef*     info = NULL;

      if (iter == calls.end())
      {
        info          = new ReturnByRef(fn);
        calls[fn->id] = info;
      }
      else
      {
        info          = iter->second;
      }

      info->addCall(call);
    }
  }
}
Ejemplo n.º 4
0
// Calculates maximum of a given function, including its coordinates.
Extremum get_peak(MeshFunction *sln)
{
  Quad2D* quad = &g_quad_2d_std;
  sln->set_quad_2d(quad);
  Element* e;
  Mesh* mesh = sln->get_mesh();
  
  scalar peak = 0.0;
  double pos_x = 0.0;
  double pos_y = 0.0;
  
  for_all_active_elements(e, mesh)
  {
    update_limit_table(e->get_mode());
    sln->set_active_element(e);
    RefMap* ru = sln->get_refmap();
    int o = sln->get_fn_order() + ru->get_inv_ref_order();
    limit_order(o);
    sln->set_quad_order(o, H2D_FN_VAL);
    scalar *uval = sln->get_fn_values();
    int np = quad->get_num_points(o);
    double* x = ru->get_phys_x(o);
    double* y = ru->get_phys_y(o);
    
    for (int i = 0; i < np; i++)
      if (uval[i] > peak) {
        peak = uval[i];
        pos_x = x[i];
        pos_y = y[i];
      }
  }
Ejemplo n.º 5
0
//------------------------------------------------------------------------------
// Compute marked boundary length 
//
double CalculateBoundaryLength(Mesh* mesh, int bdryMarker)
{
  // Variables declaration.
  Element* e;
  double length = 0;
  RefMap rm;
  rm.set_quad_2d(&g_quad_2d_std);
  Quad2D * quad = rm.get_quad_2d();
  int points_location;
  double3* points;
  int np;
  double3* tangents;

  // Loop through all boundary faces of all active elements.
  for_all_active_elements(e, mesh) {
    for(int edge = 0; edge < e->nvert; ++edge) {
      if ((e->en[edge]->bnd) && (e->en[edge]->marker == bdryMarker)) {
        rm.set_active_element(e);
        points_location = quad->get_edge_points(edge);
        points = quad->get_points(points_location);
        np = quad->get_num_points(points_location);
        tangents = rm.get_tangent(edge, points_location);
        for(int i = 0; i < np; i++) {
          // Weights sum up to two on every edge, therefore the division by two must be present.
          length +=  0.5 * points[i][2] * tangents[i][2];
        }
      }
    }
  }
  return length;
} // end of CalculateBoundaryLength()
Ejemplo n.º 6
0
/// Calculates the absolute error between sln1 and sln2 using function fn
double calc_error(double (*fn)(MeshFunction*, MeshFunction*, int, QuadPt3D*), MeshFunction *sln1, MeshFunction *sln2) {
	_F_
	Mesh *meshes[2] = { sln1->get_mesh(), sln2->get_mesh() };
	Transformable *tr[2] = { sln1, sln2 };
	Traverse trav;
	trav.begin(2, meshes, tr);

	double error = 0.0;
	Element **ee;
	while ((ee = trav.get_next_state(NULL, NULL)) != NULL) {
		ElementMode3D mode = ee[0]->get_mode();

		RefMap *ru = sln1->get_refmap();
		Ord3 order = max(sln1->get_fn_order(), sln2->get_fn_order()) + ru->get_inv_ref_order();
		order.limit();

		Quad3D *quad = get_quadrature(mode);
		int np = quad->get_num_points(order);
		QuadPt3D *pt = quad->get_points(order);

		error += fn(sln1, sln2, np, pt);
	}
	trav.finish();

	return error > H3D_TINY ? sqrt(error) : error;		// do not ruin the precision by taking the sqrt
}
Ejemplo n.º 7
0
// Integral over the active core.
double integrate(MeshFunction* sln, int marker)
{
  Quad2D* quad = &g_quad_2d_std;
  sln->set_quad_2d(quad);

  double integral = 0.0;
  Element* e;
  Mesh* mesh = sln->get_mesh();

  for_all_active_elements(e, mesh)
  {
    if (e->marker == marker)
    {
      update_limit_table(e->get_mode());
      sln->set_active_element(e);
      RefMap* ru = sln->get_refmap();
      int o = sln->get_fn_order() + ru->get_inv_ref_order();
      limit_order(o);
      sln->set_quad_order(o, H2D_FN_VAL);
      scalar *uval = sln->get_fn_values();
      double* x = ru->get_phys_x(o);
      double result = 0.0;
      h1_integrate_expression(x[i] * uval[i]);
      integral += result;
    }
  }

  return 2.0 * M_PI * integral;
}
Ejemplo n.º 8
0
void CacheGitDirectory::registerEntryInRefMap(const std::string& hash,
                                              RefMap& refMap) {
  assert(isInRef());

  /* Find the cache entry that corresponds to this hash.
   * Create a new entry if not found. */
  auto itFind = gitHashMap_.find(hash);
  GitCacheEntry* entry;
  if (itFind == gitHashMap_.end()) {
    entry = new GitCacheEntry();
    entry->hash = hash;
    gitHashMap_[hash] = entry;
  } else {
    entry = itFind->second;
  }

  /* Look in the refMap for any CacheEntry that was already linked to the
   * current git ref. */
  auto itPrevEntry = refMap.find(currentGitRef_);
  if (itPrevEntry != refMap.end()) {
    GitCacheEntry* prevEntry = itPrevEntry->second;
    assert(prevEntry->numGitRefs > 0);
    prevEntry->numGitRefs--;
    if (prevEntry->numGitRefs == 0 && prevEntry != entry) {
      DLOG(INFO) << "deleting " << prevEntry->hash;
      cacheFs_.delEntry(prevEntry->hash);
      gitHashMap_.erase(prevEntry->hash);
      delete prevEntry;
    }
  }

  refMap[currentGitRef_] = entry;
  entry->numGitRefs++;
}
Ejemplo n.º 9
0
void loadNiTriShapeData(Niflib::NiTriShapeRef parent, Niflib::NiTriShapeDataRef data, 
								RefMap& refmap) {
	Renderable *result;

	if (parent->GetSkinInstance()) {
		SkinnedMesh *mesh = new SkinnedMesh(true);

		loadNiTriShapeVertices(mesh, data);
		loadNiTriShapeMaterial(mesh, parent);
		loadNiSkinInstance(mesh, parent->GetSkinInstance(), refmap);
		mesh->parent = refmap.getNode(parent);

		result = mesh;
	}
	else {
		Mesh *mesh = new Mesh(true);

		loadNiTriShapeVertices(mesh, data);
		loadNiTriShapeMaterial(mesh, parent);
		mesh->parent = refmap.getNode(parent);

		result = mesh;
	}

	refmap.currentModel->addRenderable(result);
}
Ejemplo n.º 10
0
// Integral over the active core.
double integrate(MeshFunction<double>* sln, std::string area)
{
  Quad2D* quad = &g_quad_2d_std;
  sln->set_quad_2d(quad);
  
  double integral = 0.0;
  Element* e;
  Mesh* mesh = const_cast<Mesh*>(sln->get_mesh());
  int marker = mesh->get_element_markers_conversion().get_internal_marker(area).marker;
  
  for_all_active_elements(e, mesh)
  {
    if (e->marker == marker)
    {
      update_limit_table(e->get_mode());
      sln->set_active_element(e);
      RefMap* ru = sln->get_refmap();
      int o = sln->get_fn_order() + ru->get_inv_ref_order();
      limit_order(o, e->get_mode());
      sln->set_quad_order(o, H2D_FN_VAL);
      double *uval = sln->get_fn_values();
      double* x = ru->get_phys_x(o);
      double result = 0.0;
      h1_integrate_expression(x[i] * uval[i]);
      integral += result;
    }
  }
  
  return 2.0 * M_PI * integral;
}
Ejemplo n.º 11
0
void ReturnByRef::apply()
{
  RefMap           map;
  RefMap::iterator iter;

  returnByRefCollectCalls(map);

  for (iter = map.begin(); iter != map.end(); iter++)
    iter->second->transform();

  for (int i = 0; i < virtualMethodTable.n; i++)
  {
    if (virtualMethodTable.v[i].key)
    {
      int  numFns = virtualMethodTable.v[i].value->n;

      for (int j = 0; j < numFns; j++)
      {
        FnSymbol* fn = virtualMethodTable.v[i].value->v[j];

        if (isTransformableFunction(fn))
          transformFunction(fn);
      }
    }
  }
}
Ejemplo n.º 12
0
// Insert pairs into available copies map
// Also, record references when they are created.
static void extractReferences(Expr* expr,
                              RefMap& refs)
{
  // We're only interested in call expressions.
  if (CallExpr* call = toCallExpr(expr))
  {
    // Only the move primitive creates an available pair.
    if (call->isPrimitive(PRIM_MOVE) || call->isPrimitive(PRIM_ASSIGN))
    {
      SymExpr* lhe = toSymExpr(call->get(1)); // Left-Hand Expression
      Symbol* lhs = lhe->var; // Left-Hand Symbol

      if (SymExpr* rhe = toSymExpr(call->get(2))) // Right-Hand Expression
      {
        Symbol* rhs = rhe->var; // Right-Hand Symbol

        if (lhs->type->symbol->hasFlag(FLAG_REF) &&
            rhs->type->symbol->hasFlag(FLAG_REF))
        {
          // This is a ref <- ref assignment.
          // Which means that the lhs is now also a reference to whatever the
          // rhs refers to.
          RefMap::iterator refDef = refs.find(rhs);
          // Refs can come from outside the function (e.g. through arguments),
          // so are not necessarily defined within the function.
          if (refDef != refs.end())
          {
            Symbol* val = refDef->second;
#if DEBUG_CP
            if (debug > 0)
              printf("Creating ref (%s[%d], %s[%d])\n",
                     lhs->name, lhs->id, val->name, val->id);
#endif
            refs.insert(RefMapElem(lhs, val));
          }
        }
      }

      if (CallExpr* rhc = toCallExpr(call->get(2)))
      {
        if (rhc->isPrimitive(PRIM_ADDR_OF))
        {
          SymExpr* rhe = toSymExpr(rhc->get(1));

          // Create the pair lhs <- &rhs.
          Symbol* lhs = lhe->var;
          Symbol* rhs = rhe->var;
#if DEBUG_CP
          if (debug > 0)
            printf("Creating ref (%s[%d], %s[%d])\n",
                   lhs->name, lhs->id, rhs->name, rhs->id);
#endif
          refs.insert(RefMapElem(lhs, rhs));
        }
      }
    }
  }
}
Ejemplo n.º 13
0
void loadNiKeyframeController(Niflib::NiKeyframeControllerRef obj, RefMap& refmap)
{
	//make a new animation controller
	KeyframeAnimationObject *result = new KeyframeAnimationObject();

	//load data
	result->length = obj->GetStopTime();

	Niflib::NiKeyframeDataRef data = Niflib::DynamicCast<Niflib::NiKeyframeData>(obj->GetData());

	for (Niflib::Key<Niflib::Vector3> key: data->GetTranslateKeys()) {
		result->positionKeys.addKey(key.time, NifToGlmVec3(key.data));
	}

	for (Niflib::Key<Niflib::Quaternion> key: data->GetQuatRotateKeys()) {
		result->rotationKeys.addKey(key.time, NifToGlmQuat(key.data));
	}

	for (Niflib::Key<float> key: data->GetScaleKeys()) {
		result->scaleKeys.addKey(key.time, glm::vec3(key.data, key.data, key.data));
	}

	result->setTarget(refmap.getNode(obj->GetTarget()));
	
	refmap.currentModel->addController(result);
}
Ejemplo n.º 14
0
void loadNiSkinInstance(SkinnedMesh *mesh, Niflib::NiSkinInstanceRef skin, RefMap& refmap)
{
	Niflib::NiSkinDataRef skindata = skin->GetSkinData();

	for (unsigned int ibone=0; ibone<skin->GetBoneCount(); ibone++) {
		mesh->bones.push_back(refmap.getNode(skin->GetBones()[ibone]));

		Niflib::Matrix44 offset = skindata->GetBoneTransform(ibone);
		mesh->boneOffsets.push_back(NifToGlmMat4(offset));

		for (Niflib::SkinWeight weight: skindata->GetBoneWeights(ibone)) {
			mesh->vertices->get(weight.index).addBone(ibone, weight.weight);
		}
	}

	mesh->root = refmap.getNode(skin->GetSkeletonRoot());
}
Ejemplo n.º 15
0
/// Calculates the norm of sln using function fn
double calc_norm(double (*fn)(MeshFunction*, int, QuadPt3D*), MeshFunction *sln) {
	_F_
	double norm = 0.0;
	Mesh *mesh = sln->get_mesh();

	FOR_ALL_ACTIVE_ELEMENTS(eid, mesh) {
		Element *e = mesh->elements[eid];
		sln->set_active_element(e);

		RefMap *ru = sln->get_refmap();
		order3_t o = sln->get_fn_order() + ru->get_inv_ref_order();
		o.limit();

		Quad3D *quad = get_quadrature(e->get_mode());
		int np = quad->get_num_points(o);
		QuadPt3D *pt = quad->get_points(o);

		norm += fn(sln, np, pt);
	}
Ejemplo n.º 16
0
void ReturnByRef::returnByRefCollectCalls(RefMap& calls, FnSet& fns)
{
  RefMap::iterator iter;

  forv_Vec(CallExpr, call, gCallExprs)
  {
    // Only transform calls that are still in the AST tree
    // (defer statement bodies have been removed at this point
    //  in this pass)
    if (call->inTree()) {

      // Only transform calls to transformable functions
      // The common case is a user-level call to a resolved function
      // Also handle the PRIMOP for a virtual method call
      if (FnSymbol* fn = call->resolvedOrVirtualFunction()) {
       TransformationKind tfKind = transformableFunctionKind(fn);
       if (tfKind == TF_FULL)
       {
        RefMap::iterator iter = calls.find(fn->id);
        ReturnByRef*     info = NULL;

        if (iter == calls.end())
        {
          info          = new ReturnByRef(fn);
          calls[fn->id] = info;
        }
        else
        {
          info          = iter->second;
        }

        info->addCall(call);
       }
       else if (tfKind == TF_ASGN)
       {
         fns.insert(fn);
       }
      }
    }
  }
}
Ejemplo n.º 17
0
void loadNiNode(Niflib::NiAVObjectRef node, RefMap& refmap) {
	//make a new node
	Node *result = refmap.getNode(node);

	//load data
	result->setName(node->GetName());
	result->setPosition(NifToGlmVec3(node->GetLocalTranslation()));
	result->setRotation(NifToGlmQuat(node->GetLocalRotation().AsQuaternion()));
	result->setScale(glm::vec3(node->GetLocalScale(),node->GetLocalScale(),node->GetLocalScale()));

	for (Niflib::NiExtraDataRef& extradata: node->GetExtraData()) {
		if (extradata->GetType().IsSameType(Niflib::NiStringExtraData::TYPE)) {
			Niflib::NiStringExtraDataRef strdata = Niflib::DynamicCast<Niflib::NiStringExtraData>(
														extradata);
			if (strdata->GetData() == "NCO") {
				refmap.hasCollision = false;
			}
		}
	}

	if (node->GetType().IsSameType(Niflib::NiTriShape::TYPE)) {
		Niflib::NiTriShapeRef temp = Niflib::DynamicCast<Niflib::NiTriShape>(node);
		Niflib::NiTriShapeDataRef tempdata = Niflib::DynamicCast<Niflib::NiTriShapeData>(temp->GetData());
		loadNiTriShapeData(temp, tempdata, refmap);
	}
	else if (node->GetType().IsSameType(Niflib::RootCollisionNode::TYPE)) {
		refmap.collisionnode = Niflib::DynamicCast<Niflib::RootCollisionNode>(node);
	}

	result->isVisible = node->GetVisibility();

	//attach this node to its parent
	Niflib::NiNodeRef parent = node->GetParent();
	if (parent) {
		Node *parnode = refmap.getNode(parent);
		parnode->addChild(result);
	}

	refmap.currentModel->addNamedNode(node->GetName(), result);
}
Ejemplo n.º 18
0
void DiscreteProblem::precalc_equi_coefs()
{
  int i, m;
  memset(equi, 0, sizeof(double) * ndofs);
  verbose("Precalculating equilibration coefficients...");

  RefMap refmap;
  AsmList al;
  Element* e;

  for (m = 0; m < neq; m++)
  {
    PrecalcShapeset* fu = pss[m];
    BiForm* bf = biform[m] + m;
    Mesh* mesh = spaces[m]->get_mesh();

    for_all_active_elements(e, mesh)
    {
      update_limit_table(e->get_mode());
      fu->set_active_element(e);
      refmap.set_active_element(e);

      spaces[m]->get_element_assembly_list(e, &al);
      for (i = 0; i < al.cnt; i++)
      {
        if (al.dof[i] < 0) continue;
        fu->set_active_shape(al.idx[i]);
        scalar sy = 0.0, un = 0.0;
        if (bf->unsym) un = bf->unsym(fu, fu, &refmap, &refmap);
        if (bf->sym)   sy = bf->sym  (fu, fu, &refmap, &refmap);
        #ifndef COMPLEX
        equi[al.dof[i]] += (sy + un) * sqr(al.coef[i]);
        #else
        equi[al.dof[i]] += 0;//std::norm(sy + un) * sqr(al.coef[i]);
        #endif
      }
    }
  }
Ejemplo n.º 19
0
/// Calculates the norm of sln using function fn
double calc_norm(double (*fn)(MeshFunction*, int, QuadPt3D*), MeshFunction *sln) {
	_F_
	double norm = 0.0;
	Mesh *mesh = sln->get_mesh();

	for(std::map<unsigned int, Element*>::iterator it = mesh->elements.begin(); it != mesh->elements.end(); it++)
		if (it->second->used && it->second->active) {
      Element *e = mesh->elements[it->first];
		  sln->set_active_element(e);

		  RefMap *ru = sln->get_refmap();
		  Ord3 o = sln->get_fn_order() + ru->get_inv_ref_order();
		  o.limit();

		  Quad3D *quad = get_quadrature(e->get_mode());
		  int np = quad->get_num_points(o);
		  QuadPt3D *pt = quad->get_points(o);

		  norm += fn(sln, np, pt);
	  }

	return norm > H3D_TINY ? sqrt(norm) : norm;			// do not ruin the precision by taking the sqrt
}
Ejemplo n.º 20
0
/// Calculate number of negative solution values.
int get_num_of_neg(MeshFunction *sln)
{
	Quad2D* quad = &g_quad_2d_std;
  sln->set_quad_2d(quad);
  Element* e;
  Mesh* mesh = sln->get_mesh();

  int n = 0;

  for_all_active_elements(e, mesh)
  {
    update_limit_table(e->get_mode());
    sln->set_active_element(e);
    RefMap* ru = sln->get_refmap();
    int o = sln->get_fn_order() + ru->get_inv_ref_order();
    limit_order(o);
    sln->set_quad_order(o, H2D_FN_VAL);
    scalar *uval = sln->get_fn_values();
    int np = quad->get_num_points(o);

		for (int i = 0; i < np; i++)
			if (uval[i] < -1e-12)
				n++;
  }
Ejemplo n.º 21
0
      void Orderizer::process_space(SpaceSharedPtr<Scalar> space, bool show_edge_orders)
      {
        // sanity check
        if (space == nullptr)
          throw Hermes::Exceptions::Exception("Space is nullptr in Orderizer:process_space().");

        if (!space->is_up_to_date())
          throw Hermes::Exceptions::Exception("The space is not up to date.");

        MeshSharedPtr mesh = space->get_mesh();

        // Reallocate.
        this->reallocate(mesh);

        RefMap refmap;

        int oo, o[6];

        // make a mesh illustrating the distribution of polynomial orders over the space
        Element* e;
        for_all_active_elements(e, mesh)
        {
          oo = o[4] = o[5] = space->get_element_order(e->id);
          if (show_edge_orders)
          for (unsigned int k = 0; k < e->get_nvert(); k++)
            o[k] = space->get_edge_order(e, k);
          else if (e->is_curved())
          {
            if (e->is_triangle())
            for (unsigned int k = 0; k < e->get_nvert(); k++)
              o[k] = oo;
            else
            for (unsigned int k = 0; k < e->get_nvert(); k++)
              o[k] = H2D_GET_H_ORDER(oo);
          }

          double3* pt;
          int np;
          double* x;
          double* y;
          if (show_edge_orders || e->is_curved())
          {
            refmap.set_quad_2d(&quad_ord);
            refmap.set_active_element(e);
            x = refmap.get_phys_x(1);
            y = refmap.get_phys_y(1);

            pt = quad_ord.get_points(1, e->get_mode());
            np = quad_ord.get_num_points(1, e->get_mode());
          }
          else
          {
            refmap.set_quad_2d(&quad_ord_simple);
            refmap.set_active_element(e);
            x = refmap.get_phys_x(1);
            y = refmap.get_phys_y(1);

            pt = quad_ord_simple.get_points(1, e->get_mode());
            np = quad_ord_simple.get_num_points(1, e->get_mode());
          }

          int id[80];
          assert(np <= 80);

          int mode = e->get_mode();
          if (e->is_quad())
          {
            o[4] = H2D_GET_H_ORDER(oo);
            o[5] = H2D_GET_V_ORDER(oo);
          }
          if (show_edge_orders || e->is_curved())
          {
            make_vert(lvert[label_count], x[0], y[0], o[4]);

            for (int i = 1; i < np; i++)
              make_vert(id[i - 1], x[i], y[i], o[(int)pt[i][2]]);

            for (int i = 0; i < num_elem[mode][1]; i++)
              this->add_triangle(id[ord_elem[mode][1][i][0]], id[ord_elem[mode][1][i][1]], id[ord_elem[mode][1][i][2]], e->marker);

            for (int i = 0; i < num_edge[mode][1]; i++)
            {
              if (e->en[ord_edge[mode][1][i][2]]->bnd || (y[ord_edge[mode][1][i][0] + 1] < y[ord_edge[mode][1][i][1] + 1]) ||
                ((y[ord_edge[mode][1][i][0] + 1] == y[ord_edge[mode][1][i][1] + 1]) &&
                (x[ord_edge[mode][1][i][0] + 1] < x[ord_edge[mode][1][i][1] + 1])))
              {
                add_edge(id[ord_edge[mode][1][i][0]], id[ord_edge[mode][1][i][1]], e->en[ord_edge[mode][1][i][2]]->marker);
              }
            }
          }
          else
          {
            make_vert(lvert[label_count], x[0], y[0], o[4]);

            for (int i = 1; i < np; i++)
              make_vert(id[i - 1], x[i], y[i], o[(int)pt[i][2]]);

            for (int i = 0; i < num_elem_simple[mode][1]; i++)
              this->add_triangle(id[ord_elem_simple[mode][1][i][0]], id[ord_elem_simple[mode][1][i][1]], id[ord_elem_simple[mode][1][i][2]], e->marker);

            for (int i = 0; i < num_edge_simple[mode][1]; i++)
              add_edge(id[ord_edge_simple[mode][1][i][0]], id[ord_edge_simple[mode][1][i][1]], e->en[ord_edge_simple[mode][1][i][2]]->marker);
          }

          double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
          for (unsigned int k = 0; k < e->get_nvert(); k++)
          {
            if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
            if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
            if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
            if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
          }
          lbox[label_count][0] = xmax - xmin;
          lbox[label_count][1] = ymax - ymin;
          ltext[label_count++] = labels[o[4]][o[5]];
        }
Ejemplo n.º 22
0
void Linearizer::process_triangle(int iv0, int iv1, int iv2, int level,
                                  scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][3];

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_tri[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_tri[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = tri_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max)
      {
        // do not split if the whole triangle is above the specified maximum value
        split = false;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double err = fabs(getval(idx[0]) - midval[2][0]) +
                     fabs(getval(idx[1]) - midval[2][1]) +
                     fabs(getval(idx[2]) - midval[2][2]);
        split = !finite(err) || err > max*3*eps;
      }

      // do the same for the curvature
      if (!split && (curved || disp))
      {
        for (i = 0; i < 3; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1.5e-3))
            { split = true; break; }
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = (fabs(getval(8) - 0.5*(midval[2][0] + midval[2][1])) +
                 fabs(getval(9) - 0.5*(midval[2][1] + midval[2][2])) +
                 fabs(getval(4) - 0.5*(midval[2][2] + midval[2][0]))) > max*3*eps;
      }
    }

    // split the triangle if the error is too large, otherwise produce a linear triangle
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 3; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge vertices
      int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getval(idx[0]));
      int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getval(idx[1]));
      int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getval(idx[2]));

      // recur to sub-elements
      sln->push_transform(0);  process_triangle(iv0, mid0, mid2,  level+1, val, phx, phy, tri_indices[1]);  sln->pop_transform();
      sln->push_transform(1);  process_triangle(mid0, iv1, mid1,  level+1, val, phx, phy, tri_indices[2]);  sln->pop_transform();
      sln->push_transform(2);  process_triangle(mid2, mid1, iv2,  level+1, val, phx, phy, tri_indices[3]);  sln->pop_transform();
      sln->push_transform(3);  process_triangle(mid1, mid2, mid0, level+1, val, phx, phy, tri_indices[4]);  sln->pop_transform();
      return;
    }
  }

  // no splitting: output a linear triangle
  add_triangle(iv0, iv1, iv2);
}
Ejemplo n.º 23
0
void Linearizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level,
                              scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][5];

  // try not to split through the vertex with the largest value
  int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1;
  int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3;
  a = (verts[a][2] > verts[b][2]) ? a : b;
  int flip = (a == iv1 || a == iv3) ? 1 : 0;

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1)) // this is an optimization: do the following only every other time
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_quad[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_quad[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = quad_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
      midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
      midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
    };

    // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
    midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;


    // determine whether or not to split the element
    int split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps) ? 3 : 0;
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max
                         && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max)
      {
        // do not split if the whole quad is above the specified maximum value
        split = 0;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double herr = fabs(getval(idx[1]) - midval[2][1]) + fabs(getval(idx[3]) - midval[2][3]);
        double verr = fabs(getval(idx[0]) - midval[2][0]) + fabs(getval(idx[2]) - midval[2][2]);
        double err  = fabs(getval(idx[4]) - midval[2][4]) + herr + verr;
        split = (!finite(err) || err > max*4*eps) ? 3 : 0;

        // decide whether to split horizontally or vertically only
        if (level > 0 && split)
          if (herr > 5*verr)
            split = 1; // h-split
          else if (verr > 5*herr)
            split = 2; // v-split
      }

      // also decide whether to split because of the curvature
      if (split != 3 && (curved || disp))
      {
        double cm2 = sqr(cmax*5e-4);
        if (sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 ||
            sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1;
        if (sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 ||
            sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2;

        /*for (i = 0; i < 5; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1e-3))
            { split = 1; break; }*/
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = ((fabs(getval(13) - 0.5*(midval[2][0] + midval[2][1])) +
                  fabs(getval(17) - 0.5*(midval[2][1] + midval[2][2])) +
                  fabs(getval(20) - 0.5*(midval[2][2] + midval[2][3])) +
                  fabs(getval(9)  - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0;
      }
    }

    // split the quad if the error is too large, otherwise produce two linear triangles
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 5; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge and mid-element vertices
      int mid0, mid1, mid2, mid3, mid4;
      if (split != 1) mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], getval(idx[0]));
      if (split != 2) mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], getval(idx[1]));
      if (split != 1) mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], getval(idx[2]));
      if (split != 2) mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], getval(idx[3]));
      if (split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getval(idx[4]));

      // recur to sub-elements
      if (split == 3)
      {
        sln->push_transform(0);  process_quad(iv0, mid0, mid4, mid3, level+1, val, phx, phy, quad_indices[1]);  sln->pop_transform();
        sln->push_transform(1);  process_quad(mid0, iv1, mid1, mid4, level+1, val, phx, phy, quad_indices[2]);  sln->pop_transform();
        sln->push_transform(2);  process_quad(mid4, mid1, iv2, mid2, level+1, val, phx, phy, quad_indices[3]);  sln->pop_transform();
        sln->push_transform(3);  process_quad(mid3, mid4, mid2, iv3, level+1, val, phx, phy, quad_indices[4]);  sln->pop_transform();
      }
      else if (split == 1) // h-split
      {
        sln->push_transform(4);  process_quad(iv0, iv1, mid1, mid3, level+1, val, phx, phy, quad_indices[5]);  sln->pop_transform();
        sln->push_transform(5);  process_quad(mid3, mid1, iv2, iv3, level+1, val, phx, phy, quad_indices[6]);  sln->pop_transform();
      }
      else // v-split
      {
        sln->push_transform(6);  process_quad(iv0, mid0, mid2, iv3, level+1, val, phx, phy, quad_indices[7]);  sln->pop_transform();
        sln->push_transform(7);  process_quad(mid0, iv1, iv2, mid2, level+1, val, phx, phy, quad_indices[8]);  sln->pop_transform();
      }
      return;
    }
  }

  // output two linear triangles,
  if (!flip)
  {
    add_triangle(iv3, iv0, iv1);
    add_triangle(iv1, iv2, iv3);
  }
  else
  {
    add_triangle(iv0, iv1, iv2);
    add_triangle(iv2, iv3, iv0);
  }
}
Ejemplo n.º 24
0
void Orderizer::process_solution(Space* space)
{
  // sanity check
  if (space == NULL) error("Space is NULL in Orderizer:process_solution().");

  if (!space->is_up_to_date())
    error("The space is not up to date.");

  int type = 1;

  nv = nt = ne = nl = 0;
  del_slot = -1;

  // estimate the required number of vertices and triangles
  Mesh* mesh = space->get_mesh();
  if (mesh == NULL) {
    error("Mesh is NULL in Orderizer:process_solution().");
  }
  int nn = mesh->get_num_active_elements();
  int ev = 77 * nn, et = 64 * nn, ee = 16 * nn, el = nn + 10;

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(lvert, int, cl1, el);
  lin_init_array(ltext, char*, cl2, el);
  lin_init_array(lbox, double2, cl3, el);
  info = NULL;

  int oo, o[6];

  RefMap refmap;
  refmap.set_quad_2d(&quad_ord);

  // make a mesh illustrating the distribution of polynomial orders over the space
  Element* e;
  for_all_active_elements(e, mesh)
  {
    oo = o[4] = o[5] = space->get_element_order(e->id);
    for (unsigned int k = 0; k < e->nvert; k++)
      o[k] = space->get_edge_order(e, k);

    refmap.set_active_element(e);
    double* x = refmap.get_phys_x(type);
    double* y = refmap.get_phys_y(type);

    double3* pt = quad_ord.get_points(type);
    int np = quad_ord.get_num_points(type);
    int id[80];
    assert(np <= 80);

    #define make_vert(index, x, y, val) \
      { (index) = add_vertex(); \
      verts[index][0] = (x); \
      verts[index][1] = (y); \
      verts[index][2] = (val); }

    int mode = e->get_mode();
    if (e->is_quad())
    {
      o[4] = H2D_GET_H_ORDER(oo);
      o[5] = H2D_GET_V_ORDER(oo);
    }
    make_vert(lvert[nl], x[0], y[0], o[4]);

    for (int i = 1; i < np; i++)
      make_vert(id[i-1], x[i], y[i], o[(int) pt[i][2]]);

    for (int i = 0; i < num_elem[mode][type]; i++)
      add_triangle(id[ord_elem[mode][type][i][0]], id[ord_elem[mode][type][i][1]], id[ord_elem[mode][type][i][2]]);

    for (int i = 0; i < num_edge[mode][type]; i++)
    {
      if (e->en[ord_edge[mode][type][i][2]]->bnd || (y[ord_edge[mode][type][i][0] + 1] < y[ord_edge[mode][type][i][1] + 1]) ||
          ((y[ord_edge[mode][type][i][0] + 1] == y[ord_edge[mode][type][i][1] + 1]) &&
           (x[ord_edge[mode][type][i][0] + 1] <  x[ord_edge[mode][type][i][1] + 1])))
      {
        add_edge(id[ord_edge[mode][type][i][0]], id[ord_edge[mode][type][i][1]], 0);
      }
    }

    double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
    for (unsigned int k = 0; k < e->nvert; k++)
    {
      if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
      if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
      if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
      if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
    }
    lbox[nl][0] = xmax - xmin;
    lbox[nl][1] = ymax - ymin;
    ltext[nl++] = labels[o[4]][o[5]];
  }
Ejemplo n.º 25
0
void Liveness::emptify(RefMap &M) {
  for (auto I = M.begin(), E = M.end(); I != E; )
    I = I->second.empty() ? M.erase(I) : std::next(I);
}
Ejemplo n.º 26
0
void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
  // The LiveIn map, for each (physical) register, contains the set of live
  // reaching defs of that register that are live on entry to the associated
  // block.

  // The summary of the traversal algorithm:
  //
  // R is live-in in B, if there exists a U(R), such that rdef(R) dom B
  // and (U \in IDF(B) or B dom U).
  //
  // for (C : children) {
  //   LU = {}
  //   traverse(C, LU)
  //   LiveUses += LU
  // }
  //
  // LiveUses -= Defs(B);
  // LiveUses += UpwardExposedUses(B);
  // for (C : IIDF[B])
  //   for (U : LiveUses)
  //     if (Rdef(U) dom C)
  //       C.addLiveIn(U)
  //

  // Go up the dominator tree (depth-first).
  MachineDomTreeNode *N = MDT.getNode(B);
  for (auto I : *N) {
    RefMap L;
    MachineBasicBlock *SB = I->getBlock();
    traverse(SB, L);

    for (auto S : L)
      LiveIn[S.first].insert(S.second.begin(), S.second.end());
  }

  if (Trace) {
    dbgs() << LLVM_FUNCTION_NAME << " in BB#" << B->getNumber()
           << " after recursion into";
    for (auto I : *N)
      dbgs() << ' ' << I->getBlock()->getNumber();
    dbgs() << "\n  LiveIn: " << Print<RefMap>(LiveIn, DFG);
    dbgs() << "\n  Local:  " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
  }

  // Add phi uses that are live on exit from this block.
  RefMap &PUs = PhiLOX[B];
  for (auto S : PUs)
    LiveIn[S.first].insert(S.second.begin(), S.second.end());

  if (Trace) {
    dbgs() << "after LOX\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
  }

  // Stop tracking all uses defined in this block: erase those records
  // where the reaching def is located in B and which cover all reached
  // uses.
  auto Copy = LiveIn;
  LiveIn.clear();

  for (auto I : Copy) {
    auto &Defs = LiveIn[I.first];
    NodeSet Rest;
    for (auto R : I.second) {
      auto DA = DFG.addr<DefNode*>(R);
      RegisterRef DDR = DA.Addr->getRegRef();
      NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG);
      NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
      // Defs from a different block need to be preserved. Defs from this
      // block will need to be processed further, except for phi defs, the
      // liveness of which is handled through the PhiLON/PhiLOX maps.
      if (B != BA.Addr->getCode())
        Defs.insert(R);
      else {
        bool IsPreserving = DA.Addr->getFlags() & NodeAttrs::Preserving;
        if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) {
          bool Covering = RAI.covers(DDR, I.first);
          NodeId U = DA.Addr->getReachedUse();
          while (U && Covering) {
            auto DUA = DFG.addr<UseNode*>(U);
            RegisterRef Q = DUA.Addr->getRegRef();
            Covering = RAI.covers(DA.Addr->getRegRef(), Q);
            U = DUA.Addr->getSibling();
          }
          if (!Covering)
            Rest.insert(R);
        }
      }
    }

    // Non-covering defs from B.
    for (auto R : Rest) {
      auto DA = DFG.addr<DefNode*>(R);
      RegisterRef DRR = DA.Addr->getRegRef();
      RegisterSet RRs;
      for (NodeAddr<DefNode*> TA : getAllReachingDefs(DA)) {
        NodeAddr<InstrNode*> IA = TA.Addr->getOwner(DFG);
        NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
        // Preserving defs do not count towards covering.
        if (!(TA.Addr->getFlags() & NodeAttrs::Preserving))
          RRs.insert(TA.Addr->getRegRef());
        if (BA.Addr->getCode() == B)
          continue;
        if (RAI.covers(RRs, DRR))
          break;
        Defs.insert(TA.Id);
      }
    }
  }

  emptify(LiveIn);

  if (Trace) {
    dbgs() << "after defs in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
  }

  // Scan the block for upward-exposed uses and add them to the tracking set.
  for (auto I : DFG.getFunc().Addr->findBlock(B, DFG).Addr->members(DFG)) {
    NodeAddr<InstrNode*> IA = I;
    if (IA.Addr->getKind() != NodeAttrs::Stmt)
      continue;
    for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) {
      RegisterRef RR = UA.Addr->getRegRef();
      for (auto D : getAllReachingDefs(UA))
        if (getBlockWithRef(D.Id) != B)
          LiveIn[RR].insert(D.Id);
    }
  }

  if (Trace) {
    dbgs() << "after uses in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
  }

  // Phi uses should not be propagated up the dominator tree, since they
  // are not dominated by their corresponding reaching defs.
  auto &Local = LiveMap[B];
  auto &LON = PhiLON[B];
  for (auto R : LON)
    Local.insert(R.first);

  if (Trace) {
    dbgs() << "after phi uses in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterSet>(Local, DFG) << '\n';
  }

  for (auto C : IIDF[B]) {
    auto &LiveC = LiveMap[C];
    for (auto S : LiveIn)
      for (auto R : S.second)
        if (MDT.properlyDominates(getBlockWithRef(R), C))
          LiveC.insert(S.first);
  }
}
Ejemplo n.º 27
0
double KellyTypeAdapt::calc_err_internal(Hermes::vector<Solution *> slns,
                                         Hermes::vector<double>* component_errors,
                                         unsigned int error_flags)
{    
  int n = slns.size();
  error_if (n != this->num,
            "Wrong number of solutions.");

  TimePeriod tmr;

  for (int i = 0; i < n; i++)
  {
    this->sln[i] = slns[i];
    sln[i]->set_quad_2d(&g_quad_2d_std);
  }

  have_coarse_solutions = true;
  
  WeakForm::Stage stage;

  num_act_elems = 0;
  for (int i = 0; i < num; i++)
  {
    stage.meshes.push_back(sln[i]->get_mesh());
    stage.fns.push_back(sln[i]);

    num_act_elems += stage.meshes[i]->get_num_active_elements();
    int max = stage.meshes[i]->get_max_element_id();

    if (errors[i] != NULL) delete [] errors[i];
    errors[i] = new double[max];
    memset(errors[i], 0.0, sizeof(double) * max);
  }
/*
  for (unsigned int i = 0; i < error_estimators_vol.size(); i++)
    trset.insert(error_estimators_vol[i].ext.begin(), error_estimators_vol[i].ext.end());
  for (unsigned int i = 0; i < error_estimators_surf.size(); i++)
    trset.insert(error_estimators_surf[i].ext.begin(), error_estimators_surf[i].ext.end());
*/

  double total_norm = 0.0;

  bool calc_norm = false;
  if ((error_flags & HERMES_ELEMENT_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL ||
      (error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL) calc_norm = true;

  double *norms = NULL;
  if (calc_norm)
  {
    norms = new double[num];
    memset(norms, 0.0, num * sizeof(double));
  }

  double *errors_components = new double[num];
  memset(errors_components, 0.0, num * sizeof(double));
  this->errors_squared_sum = 0.0;
  double total_error = 0.0;

  bool bnd[4];          // FIXME: magic number - maximal possible number of element surfaces
  SurfPos surf_pos[4];
  Element **ee;
  Traverse trav;

  // Reset the e->visited status of each element of each mesh (most likely it will be set to true from
  // the latest assembling procedure).
  if (ignore_visited_segments)
  {
    for (int i = 0; i < num; i++)
    {
      Element* e;
      for_all_active_elements(e, stage.meshes[i])
        e->visited = false;
    }
  }
  
  //WARNING: AD HOC debugging parameter.
  bool multimesh = false;

  // Begin the multimesh traversal.
  trav.begin(num, &(stage.meshes.front()), &(stage.fns.front()));
  while ((ee = trav.get_next_state(bnd, surf_pos)) != NULL)
  {   
    // Go through all solution components.
    for (int i = 0; i < num; i++)
    {
      if (ee[i] == NULL)
        continue;
      
      // Set maximum integration order for use in integrals, see limit_order()
      update_limit_table(ee[i]->get_mode());

      RefMap *rm = sln[i]->get_refmap();

      double err = 0.0;

      // Go through all volumetric error estimators.
      for (unsigned int iest = 0; iest < error_estimators_vol.size(); iest++)
      {
        // Skip current error estimator if it is assigned to a different component or geometric area
        // different from that of the current active element.
        if (error_estimators_vol[iest]->i != i)
          continue;
        /*
        if (error_estimators_vol[iest].area != ee[i]->marker)
          continue;
          */
        else if (error_estimators_vol[iest]->area != HERMES_ANY)
          continue;

        err += eval_volumetric_estimator(error_estimators_vol[iest], rm);
      }

      // Go through all surface error estimators (includes both interface and boundary est's).
      for (unsigned int iest = 0; iest < error_estimators_surf.size(); iest++)
      {
        if (error_estimators_surf[iest]->i != i)
          continue;

        for (int isurf = 0; isurf < ee[i]->get_num_surf(); isurf++)
        {
            /*
          if (error_estimators_surf[iest].area > 0 &&
              error_estimators_surf[iest].area != surf_pos[isurf].marker) continue;
          */
          if (bnd[isurf])   // Boundary
          {
            if (error_estimators_surf[iest]->area == H2D_DG_INNER_EDGE) continue;
            
            /*
            if (boundary_markers_conversion.get_internal_marker(error_estimators_surf[iest].area) < 0 &&
                error_estimators_surf[iest].area != HERMES_ANY) continue;
            */    
            
            err += eval_boundary_estimator(error_estimators_surf[iest], rm, surf_pos);
          }
          else              // Interface
          {
            if (error_estimators_surf[iest]->area != H2D_DG_INNER_EDGE) continue;

            /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
            
            // 5 is for bits per page in the array.
            LightArray<NeighborSearch*> neighbor_searches(5);
            unsigned int num_neighbors = 0;
            DiscreteProblem::NeighborNode* root;
            int ns_index;
            
            dp.min_dg_mesh_seq = 0;
            for(int j = 0; j < num; j++)
              if(stage.meshes[j]->get_seq() < dp.min_dg_mesh_seq || j == 0)
                dp.min_dg_mesh_seq = stage.meshes[j]->get_seq();
            
            ns_index = stage.meshes[i]->get_seq() - dp.min_dg_mesh_seq; // = 0 for single mesh
            
            // Determine the minimum mesh seq in this stage.
            if (multimesh) 
            {              
              // Initialize the NeighborSearches.
              dp.init_neighbors(neighbor_searches, stage, isurf);
              
              // Create a multimesh tree;
              root = new DiscreteProblem::NeighborNode(NULL, 0);
              dp.build_multimesh_tree(root, neighbor_searches);
              
              // Update all NeighborSearches according to the multimesh tree.
              // After this, all NeighborSearches in neighbor_searches should have the same count 
              // of neighbors and proper set of transformations
              // for the central and the neighbor element(s) alike.
              // Also check that every NeighborSearch has the same number of neighbor elements.
              for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                if(neighbor_searches.present(j)) {
                  NeighborSearch* ns = neighbor_searches.get(j);
                  dp.update_neighbor_search(ns, root);
                  if(num_neighbors == 0)
                    num_neighbors = ns->n_neighbors;
                  if(ns->n_neighbors != num_neighbors)
                    error("Num_neighbors of different NeighborSearches not matching in KellyTypeAdapt::calc_err_internal.");
                }
            }
            else
            {
              NeighborSearch *ns = new NeighborSearch(ee[i], stage.meshes[i]);
              ns->original_central_el_transform = stage.fns[i]->get_transform();
              ns->set_active_edge(isurf);
              ns->clear_initial_sub_idx();
              num_neighbors = ns->n_neighbors;
              neighbor_searches.add(ns, ns_index);
            }

            // Go through all segments of the currently processed interface (segmentation is caused
            // by hanging nodes on the other side of the interface).
            for (unsigned int neighbor = 0; neighbor < num_neighbors; neighbor++)
            {              
              if (ignore_visited_segments) {
                bool processed = true;
                for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                  if(neighbor_searches.present(j))
                    if(!neighbor_searches.get(j)->neighbors.at(neighbor)->visited) {
                      processed = false;
                      break;
                    }
                if (processed) continue;
              }
              
              // Set the active segment in all NeighborSearches
              for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                if(neighbor_searches.present(j)) {
                  neighbor_searches.get(j)->active_segment = neighbor;
                  neighbor_searches.get(j)->neighb_el = neighbor_searches.get(j)->neighbors[neighbor];
                  neighbor_searches.get(j)->neighbor_edge = neighbor_searches.get(j)->neighbor_edges[neighbor];
                }
                
              // Push all the necessary transformations to all functions of this stage.
              // The important thing is that the transformations to the current subelement are already there.
              // Also store the current neighbor element and neighbor edge in neighb_el, neighbor_edge.
              if (multimesh) 
              {
                for(unsigned int fns_i = 0; fns_i < stage.fns.size(); fns_i++)
                  for(unsigned int trf_i = 0; trf_i < neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->central_n_trans[neighbor]; trf_i++)
                    stage.fns[fns_i]->push_transform(neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->central_transformations[neighbor][trf_i]);
              }
              else
              {            
                // Push the transformations only to the solution on the current mesh
                for(unsigned int trf_i = 0; trf_i < neighbor_searches.get(ns_index)->central_n_trans[neighbor]; trf_i++)
                  stage.fns[i]->push_transform(neighbor_searches.get(ns_index)->central_transformations[neighbor][trf_i]);
              }
              /* END COPY FROM DISCRETE_PROBLEM.CPP */
              rm->force_transform(this->sln[i]->get_transform(), this->sln[i]->get_ctm());
              
              // The estimate is multiplied by 0.5 in order to distribute the error equally onto
              // the two neighboring elements.
              double central_err = 0.5 * eval_interface_estimator(error_estimators_surf[iest],
                                                                  rm, surf_pos, neighbor_searches, 
                                                                  ns_index);
              double neighb_err = central_err;

              // Scale the error estimate by the scaling function dependent on the element diameter
              // (use the central element's diameter).
              if (use_aposteriori_interface_scaling && interface_scaling_fns[i])
                central_err *= interface_scaling_fns[i](ee[i]->get_diameter());

              // In the case this edge will be ignored when calculating the error for the element on
              // the other side, add the now computed error to that element as well.
              if (ignore_visited_segments)
              {
                Element *neighb = neighbor_searches.get(i)->neighb_el;

                // Scale the error estimate by the scaling function dependent on the element diameter
                // (use the diameter of the element on the other side).
                if (use_aposteriori_interface_scaling && interface_scaling_fns[i])
                  neighb_err *= interface_scaling_fns[i](neighb->get_diameter());

                errors_components[i] += central_err + neighb_err;
                total_error += central_err + neighb_err;
                errors[i][ee[i]->id] += central_err;
                errors[i][neighb->id] += neighb_err;
              }
              else
                err += central_err;
              
              /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
              
              // Clear the transformations from the RefMaps and all functions.
              if (multimesh)
                for(unsigned int fns_i = 0; fns_i < stage.fns.size(); fns_i++)
                  stage.fns[fns_i]->set_transform(neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->original_central_el_transform);
              else
                stage.fns[i]->set_transform(neighbor_searches.get(ns_index)->original_central_el_transform);

              rm->set_transform(neighbor_searches.get(ns_index)->original_central_el_transform);

              
              /* END COPY FROM DISCRETE_PROBLEM.CPP */
            }
            
            /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
            
            if (multimesh)
              // Delete the multimesh tree;
              delete root;
            
            // Delete the neighbor_searches array.
            for(unsigned int j = 0; j < neighbor_searches.get_size(); j++) 
              if(neighbor_searches.present(j))
                delete neighbor_searches.get(j);
              
            /* END COPY FROM DISCRETE_PROBLEM.CPP */
            
          }
        }
      }

      if (calc_norm)
      {
        double nrm = eval_solution_norm(error_form[i][i], rm, sln[i]);
        norms[i] += nrm;
        total_norm += nrm;
      }

      errors_components[i] += err;
      total_error += err;
      errors[i][ee[i]->id] += err;

      ee[i]->visited = true;
    }
  }
  trav.finish();

  // Store the calculation for each solution component separately.
  if(component_errors != NULL)
  {
    component_errors->clear();
    for (int i = 0; i < num; i++)
    {
      if((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_ABS)
        component_errors->push_back(sqrt(errors_components[i]));
      else if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL)
        component_errors->push_back(sqrt(errors_components[i]/norms[i]));
      else
      {
        error("Unknown total error type (0x%x).", error_flags & HERMES_TOTAL_ERROR_MASK);
        return -1.0;
      }
    }
  }

  tmr.tick();
  error_time = tmr.accumulated();

  // Make the error relative if needed.
  if ((error_flags & HERMES_ELEMENT_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL)
  {
    for (int i = 0; i < num; i++)
    {
      Element* e;
      for_all_active_elements(e, stage.meshes[i])
        errors[i][e->id] /= norms[i];
    }
  }

  this->errors_squared_sum = total_error;

  // Element error mask is used here, because this variable is used in the adapt()
  // function, where the processed error (sum of errors of processed element errors)
  // is matched to this variable.
  if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL)
    errors_squared_sum /= total_norm;

  // Prepare an ordered list of elements according to an error.
  fill_regular_queue(&(stage.meshes.front()));
  have_errors = true;

  if (calc_norm)
    delete [] norms;
  delete [] errors_components;

  // Return error value.
  if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_ABS)
    return sqrt(total_error);
  else if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL)
    return sqrt(total_error / total_norm);
  else
  {
    error("Unknown total error type (0x%x).", error_flags & HERMES_TOTAL_ERROR_MASK);
    return -1.0;
  }
}
Ejemplo n.º 28
0
      void Linearizer::process_quad(MeshFunction<double>** fns, int iv0, int iv1, int iv2, int iv3, int level,
        double* val, double* phx, double* phy, int* idx, bool curved)
      {
        double midval[3][5];

        // try not to split through the vertex with the largest value
        int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1;
        int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3;
        a = (verts[a][2] > verts[b][2]) ? a : b;
        int flip = (a == iv1 || a == iv3) ? 1 : 0;

        if(level < LinearizerBase::get_max_level(fns[0]->get_active_element(), fns[0]->get_fn_order(), fns[0]->get_mesh()))
        {
          int i;
          if(!(level & 1)) // this is an optimization: do the following only every other time
          {
            // obtain solution values
            fns[0]->set_quad_order(1, item);
            val = fns[0]->get_values(component, value_type);
            if(auto_max)
              for (i = 0; i < lin_np_quad[1]; i++)
              {
                double v = val[i];
                if(finite(v) && fabs(v) > max)
#pragma omp critical(max)
                  if(finite(v) && fabs(v) > max)
                    max = fabs(v);
              }

              // This is just to make some sense.
              if(fabs(max) < Hermes::HermesSqrtEpsilon)
                max = Hermes::HermesSqrtEpsilon;

              idx = quad_indices[0];

              if(curved)
              {
                RefMap* refmap = fns[0]->get_refmap();
                phx = refmap->get_phys_x(1);
                phy = refmap->get_phys_y(1);

                double* dx = nullptr;
                double* dy = nullptr;

                if(this->xdisp != nullptr)
                  fns[1]->set_quad_order(1, H2D_FN_VAL);
                if(this->ydisp != nullptr)
                  fns[this->xdisp == nullptr ? 1 : 2]->set_quad_order(1, H2D_FN_VAL);
                if(this->xdisp != nullptr)
                  dx = fns[1]->get_fn_values();
                if(this->ydisp != nullptr)
                  dy = fns[this->xdisp == nullptr ? 1 : 2]->get_fn_values();
                for (i = 0; i < lin_np_quad[1]; i++)
                {
                  if(this->xdisp != nullptr)
                    phx[i] += dmult*dx[i];
                  if(this->ydisp != nullptr)
                    phy[i] += dmult*dy[i];
                }
              }
          }

          // obtain linearized values and coordinates at the midpoints
          for (i = 0; i < 3; i++)
          {
            midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
            midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
            midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
            midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
            midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
          };

          // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
          midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;

          // determine whether or not to split the element
          int split;
          if(eps >= 1.0)
          {
            // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
            split = (level < eps) ? 3 : 0;
          }
          else
          {
            if(!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max
              && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max)
            {
              // do not split if the whole quad is above the specified maximum value
              split = 0;
            }
            else
            {
              // calculate the approximate error of linearizing the normalized solution
              double herr = fabs(val[idx[1]] - midval[2][1]) + fabs(val[idx[3]] - midval[2][3]);
              double verr = fabs(val[idx[0]] - midval[2][0]) + fabs(val[idx[2]] - midval[2][2]);
              double err  = fabs(val[idx[4]] - midval[2][4]) + herr + verr;
              split = (!finite(err) || err > max*4*eps) ? 3 : 0;

              // decide whether to split horizontally or vertically only
              if(level > 0 && split)
              {
                if(herr > 5*verr)
                  split = 1; // h-split
                else if(verr > 5*herr)
                  split = 2; // v-split
              }
            }

            // also decide whether to split because of the curvature
            if(split != 3 && curved)
            {
              double cm2 = sqr(fns[0]->get_active_element()->get_diameter()*this->get_curvature_epsilon());
              if(sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 ||
                sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1;
              if(sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 ||
                sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2;
            }

            // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
            if(level == 0 && !split)
            {
              split = ((fabs(val[13] - 0.5*(midval[2][0] + midval[2][1])) +
                fabs(val[17] - 0.5*(midval[2][1] + midval[2][2])) +
                fabs(val[20] - 0.5*(midval[2][2] + midval[2][3])) +
                fabs(val[9]  - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0;
            }
          }

          // split the quad if the error is too large, otherwise produce two linear triangles
          if(split)
          {
            if(curved)
              for (i = 0; i < 5; i++)
              {
                midval[0][i] = phx[idx[i]];
                midval[1][i] = phy[idx[i]];
              }

              // obtain mid-edge and mid-element vertices
              int mid0, mid1, mid2, mid3, mid4;
              if(split != 1) mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], val[idx[0]]);
              if(split != 2) mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], val[idx[1]]);
              if(split != 1) mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], val[idx[2]]);
              if(split != 2) mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], val[idx[3]]);
              if(split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], val[idx[4]]);

              if(!this->exceptionMessageCaughtInParallelBlock.empty())
                return;

              // recur to sub-elements
              if(split == 3)
              {
                this->push_transforms(fns, 0);
                process_quad(fns, iv0, mid0, mid4, mid3, level + 1, val, phx, phy, quad_indices[1], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 1);
                process_quad(fns, mid0, iv1, mid1, mid4, level + 1, val, phx, phy, quad_indices[2], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 2);
                process_quad(fns, mid4, mid1, iv2, mid2, level + 1, val, phx, phy, quad_indices[3], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 3);
                process_quad(fns, mid3, mid4, mid2, iv3, level + 1, val, phx, phy, quad_indices[4], curved);
                this->pop_transforms(fns);
              }
              else
                if(split == 1) // h-split
                {
                  this->push_transforms(fns, 4);
                  process_quad(fns, iv0, iv1, mid1, mid3, level + 1, val, phx, phy, quad_indices[5], curved);
                  this->pop_transforms(fns);

                  this->push_transforms(fns, 5);
                  process_quad(fns, mid3, mid1, iv2, iv3, level + 1, val, phx, phy, quad_indices[6], curved);
                  this->pop_transforms(fns);
                }
                else // v-split
                {
                  this->push_transforms(fns, 6);
                  process_quad(fns, iv0, mid0, mid2, iv3, level + 1, val, phx, phy, quad_indices[7], curved);
                  this->pop_transforms(fns);

                  this->push_transforms(fns, 7);
                  process_quad(fns, mid0, iv1, iv2, mid2, level + 1, val, phx, phy, quad_indices[8], curved);
                  this->pop_transforms(fns);
                }
                return;
          }
        }

        // output two linear triangles,
        if(!flip)
        {
          add_triangle(iv3, iv0, iv1, fns[0]->get_active_element()->marker);
          add_triangle(iv1, iv2, iv3, fns[0]->get_active_element()->marker);
        }
        else
        {
          add_triangle(iv0, iv1, iv2, fns[0]->get_active_element()->marker);
          add_triangle(iv2, iv3, iv0, fns[0]->get_active_element()->marker);
        }
      }
Ejemplo n.º 29
0
void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
  // The LiveIn map, for each (physical) register, contains the set of live
  // reaching defs of that register that are live on entry to the associated
  // block.

  // The summary of the traversal algorithm:
  //
  // R is live-in in B, if there exists a U(R), such that rdef(R) dom B
  // and (U \in IDF(B) or B dom U).
  //
  // for (C : children) {
  //   LU = {}
  //   traverse(C, LU)
  //   LiveUses += LU
  // }
  //
  // LiveUses -= Defs(B);
  // LiveUses += UpwardExposedUses(B);
  // for (C : IIDF[B])
  //   for (U : LiveUses)
  //     if (Rdef(U) dom C)
  //       C.addLiveIn(U)
  //

  // Go up the dominator tree (depth-first).
  MachineDomTreeNode *N = MDT.getNode(B);
  for (auto I : *N) {
    RefMap L;
    MachineBasicBlock *SB = I->getBlock();
    traverse(SB, L);

    for (auto S : L)
      LiveIn[S.first].insert(S.second.begin(), S.second.end());
  }

  if (Trace) {
    dbgs() << "\n-- BB#" << B->getNumber() << ": " << __func__
           << " after recursion into: {";
    for (auto I : *N)
      dbgs() << ' ' << I->getBlock()->getNumber();
    dbgs() << " }\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
  }

  // Add reaching defs of phi uses that are live on exit from this block.
  RefMap &PUs = PhiLOX[B];
  for (auto &S : PUs)
    LiveIn[S.first].insert(S.second.begin(), S.second.end());

  if (Trace) {
    dbgs() << "after LOX\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
  }

  // The LiveIn map at this point has all defs that are live-on-exit from B,
  // as if they were live-on-entry to B. First, we need to filter out all
  // defs that are present in this block. Then we will add reaching defs of
  // all upward-exposed uses.

  // To filter out the defs, first make a copy of LiveIn, and then re-populate
  // LiveIn with the defs that should remain.
  RefMap LiveInCopy = LiveIn;
  LiveIn.clear();

  for (const std::pair<RegisterId,NodeRefSet> &LE : LiveInCopy) {
    RegisterRef LRef(LE.first);
    NodeRefSet &NewDefs = LiveIn[LRef.Reg]; // To be filled.
    const NodeRefSet &OldDefs = LE.second;
    for (NodeRef OR : OldDefs) {
      // R is a def node that was live-on-exit
      auto DA = DFG.addr<DefNode*>(OR.first);
      NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG);
      NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
      if (B != BA.Addr->getCode()) {
        // Defs from a different block need to be preserved. Defs from this
        // block will need to be processed further, except for phi defs, the
        // liveness of which is handled through the PhiLON/PhiLOX maps.
        NewDefs.insert(OR);
        continue;
      }

      // Defs from this block need to stop the liveness from being
      // propagated upwards. This only applies to non-preserving defs,
      // and to the parts of the register actually covered by those defs.
      // (Note that phi defs should always be preserving.)
      RegisterAggr RRs(PRI);
      LRef.Mask = OR.second;

      if (!DFG.IsPreservingDef(DA)) {
        assert(!(IA.Addr->getFlags() & NodeAttrs::Phi));
        // DA is a non-phi def that is live-on-exit from this block, and
        // that is also located in this block. LRef is a register ref
        // whose use this def reaches. If DA covers LRef, then no part
        // of LRef is exposed upwards.A
        if (RRs.insert(DA.Addr->getRegRef(DFG)).hasCoverOf(LRef))
          continue;
      }

      // DA itself was not sufficient to cover LRef. In general, it is
      // the last in a chain of aliased defs before the exit from this block.
      // There could be other defs in this block that are a part of that
      // chain. Check that now: accumulate the registers from these defs,
      // and if they all together cover LRef, it is not live-on-entry.
      for (NodeAddr<DefNode*> TA : getAllReachingDefs(DA)) {
        // DefNode -> InstrNode -> BlockNode.
        NodeAddr<InstrNode*> ITA = TA.Addr->getOwner(DFG);
        NodeAddr<BlockNode*> BTA = ITA.Addr->getOwner(DFG);
        // Reaching defs are ordered in the upward direction.
        if (BTA.Addr->getCode() != B) {
          // We have reached past the beginning of B, and the accumulated
          // registers are not covering LRef. The first def from the
          // upward chain will be live.
          // Subtract all accumulated defs (RRs) from LRef.
          RegisterAggr L(PRI);
          L.insert(LRef).clear(RRs);
          assert(!L.empty());
          NewDefs.insert({TA.Id,L.begin()->second});
          break;
        }

        // TA is in B. Only add this def to the accumulated cover if it is
        // not preserving.
        if (!(TA.Addr->getFlags() & NodeAttrs::Preserving))
          RRs.insert(TA.Addr->getRegRef(DFG));
        // If this is enough to cover LRef, then stop.
        if (RRs.hasCoverOf(LRef))
          break;
      }
    }
  }

  emptify(LiveIn);

  if (Trace) {
    dbgs() << "after defs in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
  }

  // Scan the block for upward-exposed uses and add them to the tracking set.
  for (auto I : DFG.getFunc().Addr->findBlock(B, DFG).Addr->members(DFG)) {
    NodeAddr<InstrNode*> IA = I;
    if (IA.Addr->getKind() != NodeAttrs::Stmt)
      continue;
    for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) {
      if (UA.Addr->getFlags() & NodeAttrs::Undef)
        continue;
      RegisterRef RR = PRI.normalize(UA.Addr->getRegRef(DFG));
      for (NodeAddr<DefNode*> D : getAllReachingDefs(UA))
        if (getBlockWithRef(D.Id) != B)
          LiveIn[RR.Reg].insert({D.Id,RR.Mask});
    }
  }

  if (Trace) {
    dbgs() << "after uses in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
  }

  // Phi uses should not be propagated up the dominator tree, since they
  // are not dominated by their corresponding reaching defs.
  RegisterAggr &Local = LiveMap[B];
  RefMap &LON = PhiLON[B];
  for (auto &R : LON) {
    LaneBitmask M;
    for (auto P : R.second)
      M |= P.second;
    Local.insert(RegisterRef(R.first,M));
  }

  if (Trace) {
    dbgs() << "after phi uses in block\n";
    dbgs() << "  LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
    dbgs() << "  Local:  " << Print<RegisterAggr>(Local, DFG) << '\n';
  }

  for (auto C : IIDF[B]) {
    RegisterAggr &LiveC = LiveMap[C];
    for (const std::pair<RegisterId,NodeRefSet> &S : LiveIn)
      for (auto R : S.second)
        if (MDT.properlyDominates(getBlockWithRef(R.first), C))
          LiveC.insert(RegisterRef(S.first, R.second));
  }
}
Ejemplo n.º 30
0
void Vectorizer::process_triangle(int iv0, int iv1, int iv2, int level,
                                  scalar* xval, scalar* yval, double* phx, double* phy, int* idx)
{
  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values and physical element coordinates
      xsln->set_quad_order(1, xitem);
      ysln->set_quad_order(1, yitem);
      xval = xsln->get_values(xia, xib);
      yval = ysln->get_values(yia, yib);
      for (i = 0; i < lin_np_tri[1]; i++) {
        double m = getmag(i);
        if (finite(m) && fabs(m) > max) max = fabs(m);
      }

      if (curved)
      {
        RefMap* refmap = xsln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);
      }
      idx = tri_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    double midval[4][3];
    for (i = 0; i < 4; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      //if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }
    else
    {
      // calculate the approximate error of linearizing the normalized solution
      double err = fabs(getmag(idx[0]) - midmag(0)) +
                   fabs(getmag(idx[1]) - midmag(1)) +
                   fabs(getmag(idx[2]) - midmag(2));
      split = !finite(err) || err > max*3*eps;

      // do the same for the curvature
      if (curved && !split)
      {
        double cerr = 0.0, cden = 0.0; // fixme
        for (i = 0; i < 3; i++)
        {
          cerr += fabs(phx[idx[i]] - midval[0][i]) + fabs(phy[idx[i]] - midval[1][i]);
          cden += fabs(phx[idx[i]]) + fabs(phy[idx[i]]);
        }
        split = (cerr > cden*2.5e-4);
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = (fabs(getmag(8) - 0.5*(midmag(0) + midmag(1))) +
                 fabs(getmag(9) - 0.5*(midmag(1) + midmag(2))) +
                 fabs(getmag(4) - 0.5*(midmag(2) + midmag(0)))) > max*3*eps;
      }
    }

    // split the triangle if the error is too large, otherwise produce a linear triangle
    if (split)
    {
      if (curved)
        for (i = 0; i < 3; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge vertices
      int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getvalx(idx[0]), getvaly(idx[0]));
      int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getvalx(idx[1]), getvaly(idx[1]));
      int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getvalx(idx[2]), getvaly(idx[2]));

      // recur to sub-elements
      push_transform(0);  process_triangle(iv0, mid0, mid2,  level+1, xval, yval, phx, phy, tri_indices[1]);  pop_transform();
      push_transform(1);  process_triangle(mid0, iv1, mid1,  level+1, xval, yval, phx, phy, tri_indices[2]);  pop_transform();
      push_transform(2);  process_triangle(mid2, mid1, iv2,  level+1, xval, yval, phx, phy, tri_indices[3]);  pop_transform();
      push_transform(3);  process_triangle(mid1, mid2, mid0, level+1, xval, yval, phx, phy, tri_indices[4]);  pop_transform();
      return;
    }
  }

  // no splitting: output a linear triangle
  add_triangle(iv0, iv1, iv2);
}