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); }
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); }
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); }
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); }
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); }
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; }
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); }
// 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; }
//----------------------------------------------------------- // 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); }
//----------------------------------------------------------- // 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(¢er); // 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; }
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); }