예제 #1
0
void NuTo::Structure::InterpolationTypeAdd(int rInterpolationTypeId, NuTo::Node::eDof rDofType,
                                           NuTo::Interpolation::eTypeOrder rTypeOrder, const Eigen::VectorXi& rDegree,
                                           const std::vector<Eigen::VectorXd>& rKnots, const Eigen::MatrixXd& rWeights)
{
    InterpolationType* interpolationType = InterpolationTypeGet(rInterpolationTypeId);
    interpolationType->AddDofInterpolation(rDofType, rTypeOrder, rDegree, rKnots, rWeights);

    eIntegrationType integrationTypeEnum = interpolationType->GetStandardIntegrationType();
    const IntegrationTypeBase& integrationType = *this->GetPtrIntegrationType(integrationTypeEnum);

    interpolationType->ClearCache();

    // update all elements
    // disable show time

    bool showTime = GetShowTime();
    SetShowTime(false);

    int elementGroupId = GroupCreate("Elements");
    GroupAddElementFromType(elementGroupId, rInterpolationTypeId);

    for (int elementId : GroupGetMemberIds(elementGroupId))
    {
        ElementBase* element = ElementGetElementPtr(elementId);
        element->SetIntegrationType(integrationType);
    }

    GroupDelete(elementGroupId);
    UpdateDofStatus();
    SetShowTime(showTime);
}
예제 #2
0
void NuTo::Structure::InterpolationTypeAdd(
        int rInterpolationTypeId, NuTo::Node::eDof rDofType,
        NuTo::Interpolation::eTypeOrder rTypeOrder = Interpolation::eTypeOrder::EQUIDISTANT1)
{
    InterpolationType& interpolationType = *InterpolationTypeGet(rInterpolationTypeId);
    interpolationType.AddDofInterpolation(rDofType, rTypeOrder);

    eIntegrationType integrationTypeEnum = interpolationType.GetStandardIntegrationType();
    const IntegrationTypeBase& integrationType = *this->GetPtrIntegrationType(integrationTypeEnum);

    interpolationType.ClearCache();

    // update all elements
    // disable show time

    bool showTime = GetShowTime();
    SetShowTime(false);

    int elementGroupId = GroupCreate(eGroupId::Elements);
    GroupAddElementFromType(elementGroupId, rInterpolationTypeId);

    for (int elementId : GroupGetMemberIds(elementGroupId))
    {
        ElementBase* element = ElementGetElementPtr(elementId);
        element->SetIntegrationType(integrationType);
    }

    GroupDelete(elementGroupId);
    UpdateDofStatus();
    SetShowTime(showTime);
}
예제 #3
0
void NuTo::Structure::ElementCreate(int rElementNumber, int rInterpolationTypeId, const Eigen::VectorXi& rNodeNumbers,
                                    const Eigen::MatrixXd& rKnots, const Eigen::VectorXi& rKnotIDs)
{
    // convert node numbers to pointer
    std::vector<NodeBase*> nodeVector;
    for (int iNode = 0; iNode < rNodeNumbers.rows(); iNode++)
        nodeVector.push_back(NodeGetNodePtr(rNodeNumbers(iNode)));

    boost::ptr_map<int, InterpolationType>::iterator itIterator = mInterpolationTypeMap.find(rInterpolationTypeId);

    if (itIterator == mInterpolationTypeMap.end())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Interpolation type does not exist.");

    InterpolationType& interpolationType = *itIterator->second;

    if (not interpolationType.IsDof(Node::eDof::COORDINATES))
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation required.");

    unsigned int numNodesCoordinates = interpolationType.Get(Node::eDof::COORDINATES).GetNumNodes();
    if (numNodesCoordinates != nodeVector.size())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation requires " +
                                                           std::to_string(numNodesCoordinates) + " nodes. " +
                                                           std::to_string(nodeVector.size()) + " are provided.");

    interpolationType.ClearCache();
    const auto& integrationType = *GetPtrIntegrationType(interpolationType.GetStandardIntegrationType());

    ElementBase* ptrElement = nullptr;
    switch (interpolationType.GetShapeType())
    {
    case NuTo::Interpolation::eShapeType::SPRING:
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Element1DSpring currently not implemented.");
        break;
    case NuTo::Interpolation::eShapeType::TRUSS1D:
    case NuTo::Interpolation::eShapeType::TRUSSXD:
    case NuTo::Interpolation::eShapeType::TRIANGLE2D:
    case NuTo::Interpolation::eShapeType::QUAD2D:
    case NuTo::Interpolation::eShapeType::TETRAHEDRON3D:
    case NuTo::Interpolation::eShapeType::BRICK3D:
    case NuTo::Interpolation::eShapeType::INTERFACE:
        throw NuTo::Exception(__PRETTY_FUNCTION__,
                              "Please use approriate functions for element creation, this is IGA implementation.");
        break;
    case NuTo::Interpolation::eShapeType::IGA1D:
        ptrElement = new ContinuumElementIGA<1>(nodeVector, rKnots, rKnotIDs, interpolationType, integrationType,
                                                GetDofStatus());
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::IGA2D:
        ptrElement = new ContinuumElementIGA<2>(nodeVector, rKnots, rKnotIDs, interpolationType, integrationType,
                                                GetDofStatus());
        ptrElement->CheckElement();
        break;
    default:
        throw Exception(__PRETTY_FUNCTION__, "invalid dimension.");
    }

    mElementMap.insert(rElementNumber, ptrElement);
}
예제 #4
0
void NuTo::Structure::InterpolationTypeSetIntegrationType(int rInterpolationTypeId,
                                                          IntegrationTypeBase* rIntegrationType)
{
    InterpolationType* interpolationType = InterpolationTypeGet(rInterpolationTypeId);
    interpolationType->ClearCache();

    // update all elements
    // disable show time

    bool showTime = GetShowTime();
    SetShowTime(false);

    int elementGroupId = GroupCreate("Elements");
    GroupAddElementFromType(elementGroupId, rInterpolationTypeId);

    for (int elementId : GroupGetMemberIds(elementGroupId))
    {
        ElementBase* element = ElementGetElementPtr(elementId);
        element->SetIntegrationType(*rIntegrationType);
    }

    GroupDelete(elementGroupId);
    SetShowTime(showTime);
}
예제 #5
0
void ElementsCtrlBase::show_element_popup( bool only_insert /*=false*/, const wxPoint& p /*=wxDefaultPosition*/ )
{
  // we only display if there is exactly one element selected
  if( m_selels.size() == 0 )
    return; 

  wxDELETE(m_elpopup);
  m_elpopup = new wxMenu();

  const notuniqs_type& notuniqs = wxGetApp().hudfile()->notuniq_elements();
  int i=0;
  wxMenuItem *item;
  ElementBase *el;
  for( cit_notuniqs cit = notuniqs.begin(); cit != notuniqs.end() && i <= (ID_INSERT_NOTUNIQ_END - ID_INSERT_NOTUNIQ); ++cit, ++i )
  {
    el = wxGetApp().hudfile()->find_element(*cit);
    item = m_elpopup->Append(ID_INSERT_NOTUNIQ+i, wxString::Format(_("Insert %s"), cit->c_str()), el ? el->desc() : wxT("HELP"));
    item->Enable( m_selels.size() == 1);
  }

  if( !only_insert )
  {
    m_elpopup->AppendSeparator();

    item = m_elpopup->Append( wxID_COPY, _("Copy") ); // only for 1 element selected
    item->Enable( m_selels.size() == 1 );
    item = m_elpopup->Append( wxID_PASTE, _("Paste") ); // only if there is something to copy from
    item->Enable( m_copyfrom != 0 );

    m_elpopup->AppendSeparator();

    // only enable delete if we actually can delete the element (i.e. it's a notuniq one)
    item = m_elpopup->Append( wxID_DELETE, _("Remove") ); // only for removable elements
    item->Enable( m_selels.size() > 0 );
    // only display if all selected elements are notuniqs!
    for( cit_elements cit = m_selels.begin(); cit != m_selels.end(); ++cit )
      if( !(*cit)->is_removable() )
      {
        item->Enable(false);
        break;
      }
    item = m_elpopup->Append( wxID_CLEAR, _("Reset") ); // always if something is selected
  }

  PopupMenu(m_elpopup, wxDefaultPosition);
}
예제 #6
0
int NuTo::Structure::BoundaryElementsCreate(int rElementGroupId, int rNodeGroupId, NodeBase* rControlNode)
{
    Timer timer(__FUNCTION__, GetShowTime(), GetLogger());

    // find groups
    boost::ptr_map<int, GroupBase>::iterator itGroupElements = mGroupMap.find(rElementGroupId);
    if (itGroupElements == mGroupMap.end())
        throw Exception(__PRETTY_FUNCTION__, "Group with the given identifier does not exist.");
    if (itGroupElements->second->GetType() != NuTo::eGroupId::Elements)
        throw Exception(__PRETTY_FUNCTION__, "Group is not an element group.");

    boost::ptr_map<int, GroupBase>::iterator itGroupBoundaryNodes = mGroupMap.find(rNodeGroupId);
    if (itGroupBoundaryNodes == mGroupMap.end())
        throw Exception(__PRETTY_FUNCTION__, "Group with the given identifier does not exist.");
    if (itGroupBoundaryNodes->second->GetType() != NuTo::eGroupId::Nodes)
        throw Exception(__PRETTY_FUNCTION__, "Group is not a node group.");

    Group<ElementBase>& elementGroup = *(itGroupElements->second->AsGroupElement());
    Group<NodeBase>& nodeGroup = *(itGroupBoundaryNodes->second->AsGroupNode());

    // since the search is done via the id's, the surface nodes are ptr, so make another set with the node ptrs
    std::set<const NodeBase*> nodePtrSet;
    for (auto itNode : nodeGroup)
    {
        nodePtrSet.insert(itNode.second);
    }

    std::vector<int> newBoundaryElementIds;

    // loop over all elements
    for (auto itElement : elementGroup)
    {
        ElementBase* elementPtr = itElement.second;
        const InterpolationType& interpolationType = elementPtr->GetInterpolationType();

        // std::cout << typeid(*elementPtr).name() << "\n";
        // std::cout << typeid(ContinuumElement<1>).name() << std::endl;
        if (typeid(*elementPtr) != typeid(ContinuumElement<1>) && typeid(*elementPtr) != typeid(ContinuumElement<2>) &&
            typeid(*elementPtr) != typeid(ContinuumElement<3>))
            throw Exception(__PRETTY_FUNCTION__, "Element is not a ContinuumElement.");

        // loop over all surfaces
        for (int iSurface = 0; iSurface < interpolationType.GetNumSurfaces(); ++iSurface)
        {
            bool elementSurfaceNodesMatchBoundaryNodes = true;
            Eigen::VectorXi surfaceNodeIndices = interpolationType.GetSurfaceNodeIndices(iSurface);

            int numSurfaceNodes = surfaceNodeIndices.rows();
            std::vector<const NodeBase*> surfaceNodes(numSurfaceNodes);

            for (int iSurfaceNode = 0; iSurfaceNode < numSurfaceNodes; ++iSurfaceNode)
            {
                surfaceNodes[iSurfaceNode] = elementPtr->GetNode(surfaceNodeIndices(iSurfaceNode, 0));
            }

            // check, if all surface nodes are in the node group
            for (auto& surfaceNode : surfaceNodes)
            {
                if (nodePtrSet.find(surfaceNode) == nodePtrSet.end())
                {
                    // this surface has at least one node that is not in the list, continue
                    elementSurfaceNodesMatchBoundaryNodes = false;
                    break;
                }
            }
            if (not elementSurfaceNodesMatchBoundaryNodes)
                continue;

            int surfaceId = iSurface;

            int elementId = GetUnusedId(mElementMap);

            ElementBase* boundaryElement = nullptr;
            ConstitutiveBase& constitutiveLaw = elementPtr->GetConstitutiveLaw(0);

            switch (elementPtr->GetLocalDimension())
            {
            case 1:
            {
                const auto& integrationType = *GetPtrIntegrationType(eIntegrationType::IntegrationType0DBoundary);
                auto& element = dynamic_cast<ContinuumElement<1>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<1>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<1>(element, integrationType,
                                                                                            surfaceId, rControlNode);
                break;
            }
            case 2:
            {
                eIntegrationType integrationTypeEnum;
                // check for 2D types
                switch (interpolationType.GetStandardIntegrationType())
                {
                case eIntegrationType::IntegrationType2D3NGauss1Ip:
                case eIntegrationType::IntegrationType2D4NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss1Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss3Ip:
                case eIntegrationType::IntegrationType2D4NGauss4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss2Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss6Ip:
                case eIntegrationType::IntegrationType2D4NGauss9Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss3Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss12Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss5Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto9Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto3Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto16Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto4Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto25Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto5Ip;
                    break;

                default:
                    throw Exception(__PRETTY_FUNCTION__,
                                    "Could not automatically determine integration type of the boundary element.");
                }
                const auto& integrationType = *GetPtrIntegrationType(integrationTypeEnum);
                auto& element = dynamic_cast<ContinuumElement<2>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<2>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<2>(element, integrationType,
                                                                                            surfaceId, rControlNode);

                break;
            }
            case 3:
            {
                eIntegrationType integrationTypeEnum;
                // check for 3D types
                switch (interpolationType.GetStandardIntegrationType())
                {
                case eIntegrationType::IntegrationType3D4NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D3NGauss1Ip;
                    break;

                case eIntegrationType::IntegrationType3D4NGauss4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D3NGauss3Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NGauss1Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NGauss2x2x2Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NGauss4Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto3x3x3Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto9Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto4x4x4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto16Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto5x5x5Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto16Ip;
                    break;

                default:
                    throw Exception(__PRETTY_FUNCTION__,
                                    "Could not automatically determine integration type of the boundary element.");
                }

                const auto& integrationType = *GetPtrIntegrationType(integrationTypeEnum);
                auto& element = dynamic_cast<ContinuumElement<3>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<3>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<3>(element, integrationType,
                                                                                            surfaceId, rControlNode);
                break;
            }
            default:
                throw Exception(__PRETTY_FUNCTION__, "Boundary element for Continuum element with dimension " +
                                                             std::to_string(elementPtr->GetLocalDimension()) +
                                                             "not implemented");
            }

            mElementMap.insert(elementId, boundaryElement);
            newBoundaryElementIds.push_back(elementId);

            boundaryElement->SetConstitutiveLaw(constitutiveLaw);
        }
    }

    int boundaryElementGroup = GroupCreate(eGroupId::Elements);
    for (int boundaryElementId : newBoundaryElementIds)
        GroupAddElement(boundaryElementGroup, boundaryElementId);

    return boundaryElementGroup;
}
예제 #7
0
void NuTo::Structure::ElementCreate(int rElementNumber, int rInterpolationTypeId, std::vector<NodeBase*> rNodes)
{
    boost::ptr_map<int, InterpolationType>::iterator itIterator = mInterpolationTypeMap.find(rInterpolationTypeId);

    if (itIterator == mInterpolationTypeMap.end())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Interpolation type does not exist.");

    InterpolationType& interpolationType = *itIterator->second;

    if (not interpolationType.IsDof(Node::eDof::COORDINATES))
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation required.");

    unsigned int numNodesCoordinates = interpolationType.Get(Node::eDof::COORDINATES).GetNumNodes();
    if (numNodesCoordinates != rNodes.size())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation requires " +
                                                           std::to_string(numNodesCoordinates) + " nodes. " +
                                                           std::to_string(rNodes.size()) + " are provided.");

    interpolationType.ClearCache();
    const auto& integrationType = *GetPtrIntegrationType(interpolationType.GetStandardIntegrationType());

    ElementBase* ptrElement = nullptr;
    switch (interpolationType.GetShapeType())
    {
    case NuTo::Interpolation::eShapeType::SPRING:
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Element1DSpring currently not implemented.");
        break;
    case NuTo::Interpolation::eShapeType::TRUSS1D:
        ptrElement = new ContinuumElement<1>(rNodes, interpolationType, integrationType, GetDofStatus());
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::TRUSSXD:
        ptrElement = new Element1DInXD(rNodes, interpolationType, integrationType, GetDofStatus(), mDimension);
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::TRIANGLE2D:
    case NuTo::Interpolation::eShapeType::QUAD2D:
        ptrElement = new ContinuumElement<2>(rNodes, interpolationType, integrationType, GetDofStatus());
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::TETRAHEDRON3D:
    case NuTo::Interpolation::eShapeType::BRICK3D:
    case NuTo::Interpolation::eShapeType::PRISM3D:
        ptrElement = new ContinuumElement<3>(rNodes, interpolationType, integrationType, GetDofStatus());
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::INTERFACE:
        ptrElement = new Element2DInterface(rNodes, interpolationType, integrationType, mDimension);
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::IGA1D:
        throw NuTo::Exception(
                __PRETTY_FUNCTION__,
                "Please use the ElementCreate function for IGA elements, where the knot parameters are provided.");
        break;
    default:
        throw Exception(__PRETTY_FUNCTION__, "invalid dimension.");
    }

    mElementMap.insert(rElementNumber, ptrElement);
}
예제 #8
0
// Calculate CPDI nodes, optional shape functions and optional gradients
// numDnds - number of nodes in the particle domain
// cpdi[i]->ncpos - array of coordinates for corner nodes (numDnds of them)
// cpdi[i]->inElem - the element they are in
// cpdi[i]->ws - shape function weights (numNds of them)
// cpdi[i]->wg - gradient weights (numNds of them)
// throws CommonException() if too many CPDI nodes
int ElementBase::GetCPDIFunctions(int *nds,double *fn,double *xDeriv,double *yDeriv,double *zDeriv,MPMBase *mpmptr) const
{
	int i,j,numnds;
	CPDIDomain **cpdi = mpmptr->GetCPDIInfo();
    
	// Need 8X8 for linear CPDI in 3D, 8X4 for linear in 2D and 9X4 for quadratic in 2D (max is 64)
	int cnodes[64],ncnds=0;         // corner nodes and counter for those nodes
	double wsSi[64];				// hold ws * Si(xa)
	Vector wgSi[64];				// hold wg * Si(xa)
	
	// loop over the domain nodes
	for(i=0;i<numCPDINodes;i++)
	{	// get straight grid shape functions
		ElementBase *elem = theElements[cpdi[i]->inElem];
		elem->GetNodes(&numnds,nds);
		elem->ShapeFunction(&cpdi[i]->ncpos,FALSE,&fn[1],NULL,NULL,NULL);
		
		// loop over shape grid shape functions and collect in arrays
		for(j=1;j<=numnds;j++)
		{   cnodes[ncnds] = nds[j];
			wsSi[ncnds] = cpdi[i]->ws*fn[j];
			if(xDeriv!=NULL) CopyScaleVector(&wgSi[ncnds], &cpdi[i]->wg, fn[j]);
			ncnds++;
		}
	}
	
    /*
    if(xDeriv!=NULL)
	{	cout << "Initial:" << endl;
		for(i=0;i<ncnds;i++)
		{   cout << "# node = " << cnodes[i] << ", ws*Si = " << wsSi[i] << ", wgx*Si = " << wgSi[i].x << ", wgy*Si = " << wgSi[i].y << endl;
		}
	}
    */
	
	// shell sort by node numbers in cnodes[] (always 16 for linear CPDI)
	int lognb2=(int)(log((double)ncnds)*1.442695022+1.0e-5);	// log base 2
	int k=ncnds,l,cmpNode;
	double cmpWsSi;
	Vector cmpWgSi;
	for(l=1;l<=lognb2;l++)
	{	k>>=1;		// divide by 2
		for(j=k;j<ncnds;j++)
		{	i=j-k;
			cmpNode = cnodes[j];
			cmpWsSi = wsSi[j];
			if(xDeriv!=NULL) cmpWgSi = wgSi[j];
			
			// Back up until find insertion point
			while(i>=0 && cnodes[i]>cmpNode)
			{	cnodes[i+k] = cnodes[i];
				wsSi[i+k] = wsSi[i];
				if(xDeriv!=NULL) wgSi[i+k] = wgSi[i];
				i-=k;
			}
			
			// Insert point
			cnodes[i+k]=cmpNode;
			wsSi[i+k]=cmpWsSi;
			if(xDeriv!=NULL) wgSi[i+k]=cmpWgSi;
		}
	}

    /*
 	if(xDeriv!=NULL)
    {   for(j=1;j<ncnds;j++)
        {   if(cnodes[j]<cnodes[j-1])
            {
#pragma omp critical (output)
                {   cout << "Not Sorted: " << endl;
                    for(i=0;i<ncnds;i++)
                    {   cout << "# node = " << cnodes[i] << ", ws*Si = " << wsSi[i] << ", wgx*Si = " << wgSi[i].x << ", wgy*Si = " << wgSi[i].y << endl;
                    }
                }
                break;
            }
        }
	}
    */
	
	// compact same node number
	int count = 0;
	nds[0] = -1;
	fn[0] = 1.;
	for(i=0;i<ncnds;i++)
	{   if(cnodes[i] == nds[count])
		{   fn[count] += wsSi[i];
			if(xDeriv!=NULL)
			{	xDeriv[count] += wgSi[i].x;
				yDeriv[count] += wgSi[i].y;
                zDeriv[count] += wgSi[i].z;
			}
		}
		else
		{	if(fn[count]>1.e-10)
			{	count++;		// keep only if shape is nonzero
				if(count>=maxShapeNodes)
                {	cout << "# Found " << count-1 << " nodes; need room for remaining nodes:" << endl;
                    for(j=i;j<ncnds;j++)
                    {   cout << "#   node = " << cnodes[j] << ", ws*Si = " << endl;
                    }
					throw CommonException("Too many CPDI nodes found; increase maxShapeNodes in source code by at least number of remaining nodes","ElementBase::GetCPDIFunctions");
				}
			}
			nds[count] = cnodes[i];
			fn[count] = wsSi[i];
			if(xDeriv!=NULL)
			{	xDeriv[count] = wgSi[i].x;
				yDeriv[count] = wgSi[i].y;
                zDeriv[count] = wgSi[i].z;
			}
		}
	}
	if(fn[count]<=1.e-10) count--;
	return count;
}
예제 #9
0
//-----------------------------------------------------------
// Subroutine to translate BMP file into material point
//-----------------------------------------------------------
void MPMReadHandler::TranslateBMPFiles(void)
{
	unsigned char **rows,**angleRows;
	BMPInfoHeader info,angleInfo;
	bool setAngles=FALSE;
	int numRotations=strlen(rotationAxes);
	
	// read image file
	char *bmpFullPath=archiver->ExpandOutputPath(bmpFileName);
	ReadBMPFile(bmpFullPath,info,&rows);
	delete [] bmpFullPath;
	
	// angle file name (overrides other angle settings)
	if(bmpAngleFileName[0]>0)
	{	setAngles=TRUE;
		char *bmpFullAnglePath=archiver->ExpandOutputPath(bmpAngleFileName);
		ReadBMPFile(bmpFullAnglePath,angleInfo,&angleRows);
		if(info.height!=angleInfo.height || info.width!=angleInfo.width)
			throw SAXException(BMPError("The image file and angle file sizes do not match.",bmpFileName));
		delete [] bmpFullAnglePath;
	}
	else if(numRotations>0)
	{	int i;
		for(i=0;i<numRotations;i++)
		{	char *expr=new char[strlen(angleExpr[i])+1];
			strcpy(expr,angleExpr[i]);
			if(!CreateFunction(expr,i+1))
				throw SAXException("Invalid angle expression was provided in <RotateX(YZ)> command.");
			delete [] expr;
		}
	}
	
	// bheight and bwidth provided in bmp file
	// <-1.e8 means not provided
	// negative means provided mm per pixel
	// positive is a specified size
	double xpw=-1.,ypw=-1.;
	if(bwidth<-1.e8 && bheight<-1.e8)
	{	if(!info.knowsCellSize)
			throw SAXException(BMPError("<BMP> must specify width and/or height as size or pixels per mm.",bmpFileName));
		bwidth = info.width*info.xcell;
		bheight = info.height*info.ycell;
		xpw = info.xcell;
		ypw = info.ycell;
	}
	else
	{	// provided mm per pixel
		if(bheight<0. && bheight>-1.e8)
		{	ypw = -bheight;
			bheight = ypw*(double)info.height;
		}
		if(bwidth<0. && bwidth>-1.e8)
		{	xpw = -bwidth;
			bwidth = xpw*(double)info.width;
		}
	}
	
	// total dimensions (if only one is known, find the other, never have both unknown)
	if(bheight<0) bheight=bwidth*(double)info.height/(double)info.width;
	if(bwidth<0) bwidth=bheight*(double)info.width/(double)info.height;
	
	// final mm per pixel (if needed)
	if(xpw<0.) xpw=bwidth/(double)info.width;
	if(ypw<0.) ypw=bheight/(double)info.height;
	
	// variables for scanning BMP file
	int matID;
	MPMBase *newMpt;
	int ii,k;
	Vector mpos[MaxElParticles];
	int ptFlag;
	BMPLevel *nextLevel;
	double deltax,deltay,deltaz,semiscale;
	double rmin,rmax,wtr1,wtr2,rweight;
	double cmin,cmax,wtc1,wtc2,weight;
	int r1,r2,c1,c2;
	BMPLevel *maxLevel;
	int row,col;
	ElementBase *elem;
	
	// Length/semiscale is half particle with
	//	(semiscale=4 for 2D w 4 pts per element or 3D with 8 pts per element,
	//		or 2 if 1 particle in the element)
	if(fmobj->IsThreeD())
		semiscale=2.*pow((double)fmobj->ptsPerElement,1./3.);
	else
		semiscale=2.*sqrt((double)fmobj->ptsPerElement);
    
    /* Parallelizing the following loop will speed up check meshes on Mac
        1. Will need copy of levels for each block (or pass copy of weight to BMPLevel methods)
            see BMPLevel methods: ClearWeight(),Material(double,double), MaximumWeight(double)
        2. mpCtrl->AddMaterialPoint() will need critical block
        3. FunctionValue() when setting angles uses globals they are problem for parallel
    */
	
	// scan mesh and assign material points or angles
    try
    {   for(ii=1;ii<=nelems;ii++)
        {	// skip if image not in extent of element box
            elem=theElements[ii-1];
            if(!elem->IntersectsBox(xorig,yorig,bwidth,bheight,zslice))
                continue;
            
            // load point coordinates
            elem->MPMPoints(fmobj->ptsPerElement,mpos);
        
            // half the extent of the volume of a particle
            deltax=(elem->GetDeltaX())/semiscale;
            deltay=(elem->GetDeltaY())/semiscale;
            if(fmobj->IsThreeD())
                deltaz=elem->GetDeltaZ()/semiscale;
            else
                deltaz=1.;
            if(deltaz<0.) deltaz=1.;
            
            for(k=0;k<fmobj->ptsPerElement;k++)
            {	ptFlag=1<<k;
            
                // skip if already filled
                if(elem->filled&ptFlag) continue;
                
                // if point in the view area, then check it
                if((mpos[k].x>=xorig && mpos[k].x<xorig+bwidth)
                        && (mpos[k].y>=yorig && mpos[k].y<yorig+bheight)
                             && (mpos[k].z>=zslice-deltaz && mpos[k].z<zslice+deltaz))
                {	// find range of rows and cols for pixels over this material point
                    if(yflipped)
                    {   rmin=(yorig+bheight-mpos[k].y-deltay)/ypw;
                        rmax=(yorig+bheight-mpos[k].y-deltay)/ypw;
                    }
                    else
                    {   rmin=(mpos[k].y-deltay-yorig)/ypw;
                        rmax=(mpos[k].y+deltay-yorig)/ypw;
                    }
                    r1=BMPIndex(rmin,info.height);
                    r2=BMPIndex(rmax,info.height);
                    if(r2==r1)
                    {	wtr1=wtr2=1.;
                    }
                    else
                    {	// fractional weight for first and last row in case not all within the extent
                        wtr1=(double)(r1+1)-rmin;
                        wtr2=rmax-(double)r2;
                    }
                    cmin=(mpos[k].x-deltax-xorig)/xpw;
                    cmax=(mpos[k].x+deltax-xorig)/xpw;
                    c1=BMPIndex(cmin,info.width);
                    c2=BMPIndex(cmax,info.width);
                    if(c2==c1)
                    {	wtc1=wtc2=1.;
                    }
                    else
                    {	// fractional weight for first and last col in case not all within the extent
                        wtc1=(double)(c1+1)-cmin;
                        wtc2=cmax-(double)c2;
                    }
                    
                    // find material ID or none (a hole)
                    // clear material weights
                    nextLevel=firstLevel;
                    while(nextLevel!=NULL) nextLevel=nextLevel->ClearWeight();

                    // add weights
                    for(row=r1;row<=r2;row++)
                    {	if(row==r1)
                            rweight=wtr1;
                        else if(row==r2)
                            rweight=wtr2;
                        else
                            rweight=1.;
                        for(col=c1;col<=c2;col++)
                        {	if(col==c1)
                                weight=rweight*wtc1;
                            else if(col==c2)
                                weight=rweight*wtc2;
                            else
                                weight=rweight;
                            
                            // find material at this level
                            // (note: last level with matID=0 catches empty space)
                            nextLevel=firstLevel;
                            while(nextLevel!=NULL)
                            {	matID=nextLevel->Material(rows[row][col],weight);
                                if(matID>=0) break;
                                nextLevel=(BMPLevel *)nextLevel->GetNextObject();
                            }
                        }
                    }
                    
                    // find maximum weight (matID=0 means max is empty space)
                    weight=0.;
                    maxLevel=NULL;
                    nextLevel=firstLevel;
                    while(nextLevel!=NULL) nextLevel=nextLevel->MaximumWeight(weight,&maxLevel);
                    if(maxLevel!=NULL)
                    {	matID=maxLevel->mat;
                        nextLevel=maxLevel;
                    }
                    else
                        matID=-1;

                    // create a material point if one at this spot using matID and nextLevel
                    // Note that empty spaced is not marked as filled which allows superposition of
                    // images with different materials. If want to forcefully create a hole that
                    // cannot be filled by subsequent image, will need to define a new material
                    // type that can have matID for a hole. It will not create a point, but will mark
                    // the location as filled
                    if(matID>0)
                    {	if(fmobj->IsThreeD())
                            newMpt=new MatPoint3D(ii,matID,nextLevel->angle);
                        else if(fmobj->IsAxisymmetric())
                            newMpt=new MatPointAS(ii,matID,nextLevel->angle,mpos[k].x);
                        else
                            newMpt=new MatPoint2D(ii,matID,nextLevel->angle,nextLevel->thickness);
                        newMpt->SetPosition(&mpos[k]);
                        newMpt->SetOrigin(&mpos[k]);
                        newMpt->SetVelocity(&nextLevel->vel);
                        mpCtrl->AddMaterialPoint(newMpt,nextLevel->concentration,nextLevel->temperature);
                        
                        // is there an angle image?
                        if(setAngles)
                        {	// weight average of scanned pixels
                            double totalWeight=0.;
                            double totalIntensity=0.;
                            for(row=r1;row<=r2;row++)
                            {	if(row==r1)
                                    rweight=wtr1;
                                else if(row==r2)
                                    rweight=wtr2;
                                else
                                    rweight=1.;
                                for(col=c1;col<=c2;col++)
                                {	if(col==c1)
                                        weight=rweight*wtc1;
                                    else if(col==c2)
                                        weight=rweight*wtc2;
                                    else
                                        weight=rweight;
                                    
                                    totalIntensity+=weight*angleRows[row][col];
                                    totalWeight+=weight;
                                }
                            }
                            totalIntensity/=totalWeight;
                            double matAngle=minAngle+(totalIntensity-minIntensity)*angleScale;
                            newMpt->SetAnglez0InDegrees(matAngle);
                        }
                        else
                        {	// If had Rotate commands then use them
                            SetMptAnglesFromFunctions(numRotations,&mpos[k],newMpt);
                        }
                        elem->filled|=ptFlag;
                    }
                }
            }
        }
    }
    catch(const char *msg)
    {   throw SAXException(msg);
    }
	
	// clean up
	for(row=0;row<info.height;row++)
	{	delete [] rows[row];
		if(setAngles) delete [] angleRows[row];
	}
	delete [] rows;
	if(setAngles) delete [] angleRows;
	
	// angles if allocated
	for(ii=0;ii<numRotations;ii++)
	{	delete [] angleExpr[ii];
	}
	DeleteFunction(-1);
		
}
예제 #10
0
//-----------------------------------------------------------
// Subroutine to translate BMP file into material point
// throws std::bad_alloc, SAXException()
//-----------------------------------------------------------
void FEAReadHandler::TranslateBMPFiles(void)
{
	// file info and data
	unsigned char **rows,**angleRows=NULL;
	XYInfoHeader info,angleInfo;
	
	// read image file
	char *bmpFullPath=archiver->ExpandOutputPath(bmpFileName);
	ReadBMPFile(bmpFullPath,info,&rows);
	delete [] bmpFullPath;
	
	// angle file name
	bool setAngles = false;
	if(bmpAngleFileName[0]>0)
	{	setAngles=true;
		char *bmpFullAnglePath=archiver->ExpandOutputPath(bmpAngleFileName);
		ReadBMPFile(bmpFullAnglePath,angleInfo,&angleRows);
		if(info.height!=angleInfo.height || info.width!=angleInfo.width)
			throw SAXException(BMPError("The image file and angle file sizes do not match.",bmpFileName));
		delete [] bmpFullAnglePath;
	}
	
	// get final image width, height, and size per pixel
	Vector pw;
	const char *msg = CommonReadHandler::DecodeBMPWidthAndHeight(info,bwidth,bheight,orig.z,pw,false);
	if(msg != NULL) throw SAXException(BMPError(msg,bmpFileName));
	pw.z = yflipped ? -1. : 1. ;
	
	// scan all elements - fill those that are in the area and have no material yet
	DomainMap map;
	ElementBase *elem;
	Vector center,del;
	for(int i=0;i<nelems;i++)
	{	elem=theElements[i]; 
        
		// skip if element already has a material
        if(elem->material!=NO_MATERIAL) continue;
		
		// get center (will skip unless the center of extent of the element is in the image)
		elem->GetXYZCentroid(&center);
		
		// half the extent of the element (z means 2D)
		del = MakeVector((elem->GetDeltaX())/2.,(elem->GetDeltaY())/2.,-1.);
		
		// Get range of rows and columns and their weights (or skip if not in the image)
		if(!MapDomainToImage(info,center,orig,del,pw,bwidth,bheight,map)) continue;
		
		// find maximum level and its material ID or none (a hole)
		int matID=-1;
		BMPLevel *nextLevel = FindBMPLevel(firstLevel,map,rows);
		if(nextLevel!=NULL) matID = nextLevel->Material();
		
		// set material ID if found a match
		if(matID>0)
		{	// set it
			elem->material=matID;
			
			// is there an angle image too?
			if(setAngles)
			{	double totalIntensity = FindAverageValue(map,rows);
				if(totalIntensity>0.)
				{	double matAngle=minAngle+(totalIntensity-minIntensity)*angleScale;
					elem->SetAngleInDegrees(matAngle);
				}
			}
		}
	}

	// clean up
	for(int row=0;row<info.height;row++)
	{	delete [] rows[row];
		if(setAngles) delete [] angleRows[row];
	}
	delete [] rows;
	if(setAngles) delete [] angleRows;
}
예제 #11
0
void NuTo::StructureBase::ConstraintLinearEquationNodeToElementCreate(int rNode, int rElementGroup, NuTo::Node::eDof,
                                                                      const double rTolerance,
                                                                      Eigen::Vector3d rNodeCoordOffset)
{
    const int dim = GetDimension();

    Eigen::VectorXd queryNodeCoords = NodeGetNodePtr(rNode)->Get(Node::eDof::COORDINATES);
    queryNodeCoords = queryNodeCoords + rNodeCoordOffset.head(dim);


    std::vector<int> elementGroupIds = GroupGetMemberIds(rElementGroup);

    ElementBase* elementPtr = nullptr;
    Eigen::VectorXd elementNaturalNodeCoords;
    bool nodeInElement = false;
    for (auto const& eleId : elementGroupIds)
    {
        elementPtr = ElementGetElementPtr(eleId);

        // Coordinate interpolation must be linear so the shape function derivatives are constant!
        assert(elementPtr->GetInterpolationType().Get(Node::eDof::COORDINATES).GetTypeOrder() ==
               Interpolation::eTypeOrder::EQUIDISTANT1);
        const Eigen::MatrixXd& derivativeShapeFunctionsGeometryNatural =
                elementPtr->GetInterpolationType()
                        .Get(Node::eDof::COORDINATES)
                        .DerivativeShapeFunctionsNatural(
                                Eigen::VectorXd::Zero(dim)); // just as _some_ point, as said, constant

        // real coordinates of every node in rElement
        Eigen::VectorXd elementNodeCoords = elementPtr->ExtractNodeValues(NuTo::Node::eDof::COORDINATES);

        switch (mDimension)
        {
        case 2:
        {
            Eigen::Matrix2d invJacobian =
                    dynamic_cast<ContinuumElement<2>*>(elementPtr)
                            ->CalculateJacobian(derivativeShapeFunctionsGeometryNatural, elementNodeCoords)
                            .inverse();

            elementNaturalNodeCoords = invJacobian * (queryNodeCoords - elementNodeCoords.head(2));
        }
        break;
        case 3:
        {
            Eigen::Matrix3d invJacobian =
                    dynamic_cast<ContinuumElement<3>*>(elementPtr)
                            ->CalculateJacobian(derivativeShapeFunctionsGeometryNatural, elementNodeCoords)
                            .inverse();

            elementNaturalNodeCoords = invJacobian * (queryNodeCoords - elementNodeCoords.head(3));
        }
        break;

        default:
            throw NuTo::Exception(std::string(__PRETTY_FUNCTION__) + ": \t Only implemented for 2D and 3D");
        }


        if ((elementNaturalNodeCoords.array() > -rTolerance).all() and
            elementNaturalNodeCoords.sum() <= 1. + rTolerance)
        {
            nodeInElement = true;
            break;
        }
    }

    if (not nodeInElement)
    {
        GetLogger() << "Natural node coordinates: \n" << elementNaturalNodeCoords << "\n";
        throw Exception(__PRETTY_FUNCTION__, "Node is not inside any element.");
    }

    auto shapeFunctions =
            elementPtr->GetInterpolationType().Get(Node::eDof::DISPLACEMENTS).ShapeFunctions(elementNaturalNodeCoords);

    std::vector<Constraint::Equation> equations(dim); // default construction of Equation with rhs = Constant = 0
    for (int iDim = 0; iDim < dim; ++iDim)
    {
        equations[iDim].AddTerm(Constraint::Term(*NodeGetNodePtr(rNode), iDim, 1.));
    }


    for (int iNode = 0; iNode < shapeFunctions.rows(); ++iNode)
    {
        int localNodeId = elementPtr->GetInterpolationType().Get(Node::eDof::DISPLACEMENTS).GetNodeIndex(iNode);
        auto globalNode = elementPtr->GetNode(localNodeId, Node::eDof::DISPLACEMENTS);
        //        std::cout << "globalNodeId \t" << globalNodeId << std::endl;
        double coefficient = -shapeFunctions(iNode, 0);

        for (int iDim = 0; iDim < dim; ++iDim)
            equations[iDim].AddTerm(Constraint::Term(*globalNode, iDim, coefficient));
    }
    Constraints().Add(Node::eDof::DISPLACEMENTS, equations);
}