Пример #1
0
// assemble into array used in the code
int CrackController::SetCracksArray(void)
{
    // make 0-based array of cracks
    if(numObjects==0) return false;
    crackList = new (std::nothrow) CrackHeader *[numObjects];
    if(crackList==NULL) return false;

    // fill the array
    CrackHeader *obj = (CrackHeader *)firstObject;
    numberOfCracks = 0;
    while(obj!=NULL)
    {   crackList[numberOfCracks]=obj;
        numberOfCracks++;
        obj=(CrackHeader *)obj->GetNextObject();
    }
    return true;
}
// allocate crack and material velocity fields needed for time step on real nodes
// tried critical sections when nodes changed, but it was slower
// can't use ghost nodes, because need to test all on real nodes
//
// This task only used if have cracks or in multimaterial mode
void InitVelocityFieldsTask::Execute(void)
{
	CommonException *initErr = NULL;
	
	int tp = fmobj->GetTotalNumberOfPatches();
	
#pragma omp parallel
	{
		int nds[maxShapeNodes];
		double fn[maxShapeNodes];
		
		int pn = GetPatchNumber();
		
		// do non-rigid and rigid contact materials in patch pn
		for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_CONTACT;block++)
		{   // get material point (only in this patch)
			MPMBase *mpmptr = patches[pn]->GetFirstBlockPointer(block);
			
			while(mpmptr!=NULL)
			{	const MaterialBase *matID = theMaterials[mpmptr->MatID()];		// material object for this particle
				const int matfld = matID->GetField();                           // material velocity field
				
				// get nodes and shape function for material point p
				const ElementBase *elref = theElements[mpmptr->ElemID()];		// element containing this particle
				
				// don't actually need shape functions, but need to screen out zero shape function
				// like done in subsequent tasks, otherwise node numbers will not align correctly
				// only thing used from return are numnds and nds
				int numnds;
				elref->GetShapeFunctions(&numnds,fn,nds,mpmptr);
				
				// Only need to decipher crack velocity field if has cracks (firstCrack!=NULL)
				//      and if this material allows cracks.
#ifdef COMBINE_RIGID_MATERIALS
				bool decipherCVF = firstCrack!=NULL && block!=FIRST_RIGID_CONTACT;
#else
				bool decipherCVF = firstCrack!=NULL;
#endif
				
				// Check each node
				for(int i=1;i<=numnds;i++)
				{	// use real node in this loop
					NodalPoint *ndptr = nd[nds[i]];
					
					// always zero when no cracks (or when ignoring cracks)
					short vfld = 0;
					
					// If need, find vlocity field and for each field set location
					// (above or below crack) and crack number (1 based) or 0 for NO_CRACK
					if(decipherCVF)
					{	// in CRAMP, find crack crossing and appropriate velocity field
						CrackField cfld[2];
						cfld[0].loc = NO_CRACK;			// NO_CRACK=0, ABOVE_CRACK=1, or BELOW_CRACK=2
						cfld[1].loc = NO_CRACK;
						int cfound=0;
						Vector norm;					// track normal vector for crack plane
						
						CrackHeader *nextCrack = firstCrack;
						while(nextCrack!=NULL)
						{	vfld = nextCrack->CrackCross(mpmptr->pos.x,mpmptr->pos.y,ndptr->x,ndptr->y,&norm);
							if(vfld!=NO_CRACK)
							{	cfld[cfound].loc=vfld;
								cfld[cfound].norm=norm;
								
#ifdef IGNORE_CRACK_INTERACTIONS
								// appears to always be same crack, and stop when found one
								cfld[cfound].crackNum=1;
								break;
#endif
								
								// Get crack number (default code does not ignore interactions)
								cfld[cfound].crackNum=nextCrack->GetNumber();
								cfound++;
								
								// stop if found two because code can only handle two interacting cracks
								// It exits loop now to go ahead with the first two found, by physics may be off
								if(cfound>1) break;
							}
							nextCrack=(CrackHeader *)nextCrack->GetNextObject();
						}
						
						
						// find (and allocate if needed) the velocity field
						// Use vfld=0 if no cracks found
						if(cfound>0)
						{   // In parallel, this is critical code
#pragma omp critical
							{   try
								{   vfld = ndptr->AddCrackVelocityField(matfld,cfld);
								}
								catch(CommonException err)
								{   if(initErr==NULL)
									initErr = new CommonException(err);
								}
							}
						}
						
						// set material point velocity field for this node
						mpmptr->vfld[i] = vfld;
					}
					
					// make sure material velocity field is created too
					// (Note: when maxMaterialFields==1 (Singe Mat Mode), mvf[0] is always there
					//        so no need to create it here)
					if(maxMaterialFields>1 && ndptr->NeedsMatVelocityField(vfld,matfld))
					{   // If parallel, this is critical code
#pragma omp critical
						{   try
							{   ndptr->AddMatVelocityField(vfld,matfld);
							}
							catch(CommonException err)
							{   if(initErr==NULL)
								initErr = new CommonException(err);
							}
						}
						
					}
				}
				
				// next material point
				mpmptr = (MPMBase *)mpmptr->GetNextObject();
			}
		}
	}
		
	// was there an error?
	if(initErr!=NULL) throw *initErr;
	
	// copy crack and material fields on real nodes to ghost nodes
	if(tp>1)
	{   for(int pn=0;pn<tp;pn++)
		patches[pn]->InitializationReduction();
	}
}
Пример #3
0
// Get mass matrix, find dimensionless particle locations,
//	and find grid momenta
void InitializationTask::Execute(void)
{
	CommonException *initErr = NULL;
	
	// Zero Mass Matrix and vectors
	warnings.BeginStep();
    
	int tp = fmobj->GetTotalNumberOfPatches();
#pragma omp parallel
	{
        // zero all nodal variables on real nodes
#pragma omp for
		for(int i=1;i<=nnodes;i++)
			nd[i]->InitializeForTimeStep();
		
        // zero ghost nodes in patch for this thread
        int pn = GetPatchNumber();
        patches[pn]->InitializeForTimeStep();

		// particle calculations get xipos for particles and if doing CPDI
        // precalculate CPDI info needed for subsequent shape functions
#pragma omp for nowait
		for(int p=0;p<nmpmsRC;p++)
        {   MPMBase *mpmptr = mpm[p];                                       // pointer
			const ElementBase *elref = theElements[mpmptr->ElemID()];		// element containing this particle
			try
			{	elref->GetShapeFunctionData(mpmptr);
			}
			catch(CommonException err)
			{	if(initErr==NULL)
				{
#pragma omp critical
					initErr = new CommonException(err);
				}
			}
		}
	}
	
	// was there an error?
	if(initErr!=NULL) throw *initErr;
    
	// allocate crack and material velocity fields needed for time step on real nodes
    // tried critical sections when nodes changed, but it was slower
    // can't use ghost nodes, because need to test all on real nodes
	if(firstCrack!=NULL || maxMaterialFields>1)
	{
#pragma omp parallel
        {
            int nds[maxShapeNodes];
            double fn[maxShapeNodes];
            
            //for(int pn=0;pn<tp;pn++) {
            int pn = GetPatchNumber();
		
            // do non-rigid and rigid contact materials in patch pn
            for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_CONTACT;block++)
            {   // get material point (only in this patch)
                MPMBase *mpmptr = patches[pn]->GetFirstBlockPointer(block);
                
                while(mpmptr!=NULL)
                {	const MaterialBase *matID = theMaterials[mpmptr->MatID()];		// material object for this particle
                    const int matfld = matID->GetField();                           // material velocity field
                    
                    // get nodes and shape function for material point p
                    const ElementBase *elref = theElements[mpmptr->ElemID()];		// element containing this particle
                    
                    // don't actually need shape functions, but need to screen out zero shape function
                    // like done in subsequent tasks, otherwise node numbers will not align correctly
                    // only think used from return are numnds and nds
                    int numnds;
                    elref->GetShapeFunctions(&numnds,fn,nds,mpmptr);
                    
                    // Add particle property to each node in the element
                    for(int i=1;i<=numnds;i++)
                    {	// use real node in this loop
                        NodalPoint *ndptr = nd[nds[i]];
                        
                        // always zero when no cracks
                        short vfld = 0;
#ifdef COMBINE_RIGID_MATERIALS
                        // when combining rigid particles, extrapolate all to field 0 and later
                        // copy to other active fields
                        if(firstCrack!=NULL && block!=FIRST_RIGID_CONTACT)
#else
                        if(firstCrack!=NULL)
#endif
                        {	// in CRAMP, find crack crossing and appropriate velocity field
                            CrackField cfld[2];
                            cfld[0].loc = NO_CRACK;			// NO_CRACK, ABOVE_CRACK, or BELOW_CRACK
                            cfld[1].loc = NO_CRACK;
                            int cfound=0;
                            Vector norm;
                            
                            CrackHeader *nextCrack = firstCrack;
                            while(nextCrack!=NULL)
                            {	vfld = nextCrack->CrackCross(mpmptr->pos.x,mpmptr->pos.y,ndptr->x,ndptr->y,&norm);
                                if(vfld!=NO_CRACK)
                                {	cfld[cfound].loc=vfld;
                                    cfld[cfound].norm=norm;
#ifdef IGNORE_CRACK_INTERACTIONS
                                    cfld[cfound].crackNum=1;	// appears to always be same crack, and stop when found one
                                    break;
#else
                                    cfld[cfound].crackNum=nextCrack->GetNumber();
                                    cfound++;
                                    if(cfound>1) break;			// stop if found two, if there are more then two, physics will be off
#endif
                                }
                                nextCrack=(CrackHeader *)nextCrack->GetNextObject();
                            }
                                
                            
                            // find (and allocate if needed) the velocity field
                            // Use vfld=0 if no cracks found
                            if(cfound>0)
                            {   // In parallel, this is critical code
#pragma omp critical
                                {   try
                                    {   vfld = ndptr->AddCrackVelocityField(matfld,cfld);
                                    }
                                    catch(CommonException err)
                                    {   if(initErr==NULL)
                                            initErr = new CommonException(err);
                                    }
                                }
                            }
                            
                            // set material point velocity field for this node
                            mpmptr->vfld[i] = vfld;
                        }
                        
                        // make sure material velocity field is created too
                        if(maxMaterialFields>1 && ndptr->NeedsMatVelocityField(vfld,matfld))
                        {   // If parallel, this is critical code
#pragma omp critical
                            {   try
                                {   ndptr->AddMatVelocityField(vfld,matfld);
                                }
                                catch(CommonException err)
                                {   if(initErr==NULL)
                                        initErr = new CommonException(err);
                                }
                            }
                            
                        }
                    }
                    
                    // next material point
                    mpmptr = (MPMBase *)mpmptr->GetNextObject();
                }
            }
            //}           // end for loop when not in parallel
		}
    
        // was there an error?
        if(initErr!=NULL) throw *initErr;

		// copy crack and material fields on real nodes to ghost nodes
		if(tp>1)
        {   for(int pn=0;pn<tp;pn++)
				patches[pn]->InitializationReduction();
		}
	}
    	
    // Update forces applied to particles
	MatPtLoadBC::SetParticleFext(mtime);
	
	// remove contact conditions
	CrackNode::RemoveCrackNodes();
	MaterialInterfaceNode::RemoveInterfaceNodes();
	
    // turn off isothermal ramp when done and ramp step initialization
	thermal.CheckDone(mtime);
	
}	
Пример #4
0
// Archive the results if it is time
void ArchiveData::ArchiveResults(double atime)
{
	double rho,rho0;
    double sxx,syy,sxy;
    char fname[500],fline[500];
    int i,p;
    CrackHeader *nextCrack;
	
	// test global archiving
	GlobalArchive(atime);
    
    // see if desired
    if(atime<nextArchTime) return;
    nextArchTime+=archTime;
	
	// exit if using delayed archiving
	if(atime>0.9*timestep && atime<firstArchTime) return;
    
    // get relative path name to the file
    sprintf(fname,"%s%s.%d",outputDir,archiveRoot,fmobj->mstep);
    
    // output step number, time, and file name to results file
    for(i=strlen(fname);i>=0;i--)
    {	if(fname[i]=='/') break;
    }
    sprintf(fline,"%7d %15.7e  %s",fmobj->mstep,1000.*atime,&fname[i+1]);
    cout << fline << endl;

    // open the file
	ofstream afile;
	try
	{	afile.open(fname, ios::out | ios::binary);
		if(!afile.is_open())
			FileError("Cannot open an archive file",fname,"ArchiveData::ArchiveResults");
		
		// write header created in SetArchiveHeader
		*timeStamp=1000.*atime;
		afile.write(archHeader,HEADER_LENGTH);
		if(afile.bad())
			FileError("File error writing archive file header",fname,"ArchiveData::ArchiveResults");
	}
	catch(CommonException err)
	{   // give up on hopefully temporary file problem
		cout << "# " << err.Message() << endl;
		cout << "# Will try to continue" << endl;
		if(afile.is_open()) afile.close();
		return;
	}
		
	// allocate space for one material point
	long blen=recSize;
	char *aptr=(char *)malloc(blen);
	if(aptr==NULL)
		throw CommonException("Out of memory allocating buffer for archive file","ArchiveData::ArchiveResults");
    
    // all material points
    for(p=0;p<nmpms;p++)
	{	// buffer is for one particle
    	char *app=aptr;
		
		// must have these defaults
	   
		// element ID
        *(int *)app=mpm[p]->ArchiveElemID();
        app+=sizeof(int);
        
		// mass (g)
        *(double *)app=mpm[p]->mp;
        app+=sizeof(double);
        
		// material ID
        *(short *)app=mpm[p]->ArchiveMatID();
        app+=sizeof(short);
		// fill in two zeros for byte alignment
		*app=0;
		app+=1;
		*app=0;
		app+=1;
        
		// 3D has three angles, 2D has one angle and thickness
		if(threeD)
		{	// 3 material rotation angles in degrees
			*(double *)app=mpm[p]->GetRotationZInDegrees();
			app+=sizeof(double);
			*(double *)app=mpm[p]->GetRotationYInDegrees();
			app+=sizeof(double);
			*(double *)app=mpm[p]->GetRotationXInDegrees();
			app+=sizeof(double);
		}
		else
		{	// material rotation angle in degrees
			*(double *)app=mpm[p]->GetRotationZInDegrees();
			app+=sizeof(double);
			
			// thickness (2D) in mm
			*(double *)app=mpm[p]->thickness();
			app+=sizeof(double);
		}
        
		// (x,y,z) position (mm)
        *(double *)app=mpm[p]->pos.x;
        app+=sizeof(double);
        
        *(double *)app=mpm[p]->pos.y;
        app+=sizeof(double);
		
		if(threeD)
		{	*(double *)app=mpm[p]->pos.z;
			app+=sizeof(double);
		}

		// original (x,y,z) position (mm)
        *(double *)app=mpm[p]->origpos.x;
        app+=sizeof(double);
                
        *(double *)app=mpm[p]->origpos.y;
        app+=sizeof(double);

		if(threeD)
		{	*(double *)app=mpm[p]->origpos.z;
			app+=sizeof(double);
		}

        // velocity (mm/sec)
        if(mpmOrder[ARCH_Velocity]=='Y')
        {   *(double *)app=mpm[p]->vel.x;
            app+=sizeof(double);
                
            *(double *)app=mpm[p]->vel.y;
            app+=sizeof(double);
			
			if(threeD)
			{	*(double *)app=mpm[p]->vel.z;
				app+=sizeof(double);
			}
        }

        // stress - internally it is N/m^2 cm^3/g, output in N/m^2 or Pa
        //          internal SI units are kPa/(kg/m^3)
		// For large deformation, need to convert Kirchoff Stress/rho0 to Cauchy stress
        int matid = mpm[p]->MatID();
        rho0=theMaterials[matid]->rho;
        rho = rho0/theMaterials[matid]->GetCurrentRelativeVolume(mpm[p]);
        Tensor sp = mpm[p]->ReadStressTensor();
        sxx=rho*sp.xx;
        syy=rho*sp.yy;
        sxy=rho*sp.xy;
        if(mpmOrder[ARCH_Stress]=='Y')
        {   *(double *)app=sxx;
            app+=sizeof(double);
                
            *(double *)app=syy;
            app+=sizeof(double);
            
			*(double *)app=rho*sp.zz;
            app+=sizeof(double);
                
            *(double *)app=sxy;
            app+=sizeof(double);
			
			if(threeD)
            {	*(double *)app=rho*sp.xz;
				app+=sizeof(double);
				
            	*(double *)app=rho*sp.yz;
				app+=sizeof(double);
			}
        }

        // elastic strain (absolute)
        if(mpmOrder[ARCH_Strain]=='Y')
		{	Tensor *ep=mpm[p]->GetStrainTensor();
			*(double *)app=ep->xx;
            app+=sizeof(double);
                
            *(double *)app=ep->yy;
            app+=sizeof(double);
            
			*(double *)app=ep->zz;
            app+=sizeof(double);
                
            *(double *)app=ep->xy;
            app+=sizeof(double);
			
			if(threeD)
            {	*(double *)app=ep->xz;
				app+=sizeof(double);
				
            	*(double *)app=ep->yz;
				app+=sizeof(double);
			}
        }
        
        // plastic strain (absolute)
        if(mpmOrder[ARCH_PlasticStrain]=='Y')
		{	Tensor *eplast=mpm[p]->GetPlasticStrainTensor();
            *(double *)app=eplast->xx;
            app+=sizeof(double);
                
            *(double *)app=eplast->yy;
            app+=sizeof(double);
                
            *(double *)app=eplast->zz;
            app+=sizeof(double);
                
            *(double *)app=eplast->xy;
            app+=sizeof(double);
			
			if(threeD)
            {	*(double *)app=eplast->xz;
				app+=sizeof(double);
				
            	*(double *)app=eplast->yz;
				app+=sizeof(double);
			}
        }
        
        // external work (cumulative) in J
        if(mpmOrder[ARCH_WorkEnergy]=='Y')
		{	*(double *)app=1.0e-6*mpm[p]->mp*mpm[p]->GetWorkEnergy();
            app+=sizeof(double);
        }
                
        // temperature
        if(mpmOrder[ARCH_DeltaTemp]=='Y')
        {   *(double *)app=mpm[p]->pTemperature;
            app+=sizeof(double);
        }
        
        // total plastic energy (Volume*energy) in J
        // energies in material point based on energy per unit mass
        // here need mass * U/(rho0 V0)
        if(mpmOrder[ARCH_PlasticEnergy]=='Y')
        {   *(double *)app=1.0e-6*mpm[p]->mp*mpm[p]->GetPlastEnergy();
            app+=sizeof(double);
        }
                
        // shear components (absolute)
        if(mpmOrder[ARCH_ShearComponents]=='Y')
        {   *(double *)app=mpm[p]->GetDuDy();
            app+=sizeof(double);
                
            *(double *)app=mpm[p]->GetDvDx();
            app+=sizeof(double);
        }

        // total strain energy (Volume*energy) in J
        // energies in material point based on energy per unit mass
        // here need mass * U/(rho0 V0)
        // internal units are same as stress: N/m^2 cm^3/g = microJ/g = mJ/kg
		// note that rho*energy has units J/m^3 = N/m^2 (if rho in g/cm^3)
        if(mpmOrder[ARCH_StrainEnergy]=='Y')
        {   *(double *)app=1.0e-6*mpm[p]->mp*mpm[p]->GetStrainEnergy();
            app+=sizeof(double);
        }
        
        // material history data on particle (whatever units the material chooses)
        if(mpmOrder[ARCH_History]=='Y')
        {   *(double *)app=theMaterials[mpm[p]->MatID()]->GetHistory(1,mpm[p]->GetHistoryPtr());
            app+=sizeof(double);
        }
		else if(mpmOrder[ARCH_History]!='N')
		{	if(mpmOrder[ARCH_History]&0x01)
			{   *(double *)app=theMaterials[mpm[p]->MatID()]->GetHistory(1,mpm[p]->GetHistoryPtr());
				app+=sizeof(double);
			}
			if(mpmOrder[ARCH_History]&0x02)
			{   *(double *)app=theMaterials[mpm[p]->MatID()]->GetHistory(2,mpm[p]->GetHistoryPtr());
				app+=sizeof(double);
			}
			if(mpmOrder[ARCH_History]&0x04)
			{   *(double *)app=theMaterials[mpm[p]->MatID()]->GetHistory(3,mpm[p]->GetHistoryPtr());
				app+=sizeof(double);
			}
			if(mpmOrder[ARCH_History]&0x08)
			{   *(double *)app=theMaterials[mpm[p]->MatID()]->GetHistory(4,mpm[p]->GetHistoryPtr());
				app+=sizeof(double);
			}
		}
		
		// concentration and gradients convert to wt fraction units using csat for this material
        if(mpmOrder[ARCH_Concentration]=='Y')
		{	double csat=theMaterials[mpm[p]->MatID()]->concSaturation;
		
           *(double *)app=mpm[p]->pConcentration*csat;
            app+=sizeof(double);
			
			if(mpm[p]->pDiffusion!=NULL)
			{	*(double *)app=mpm[p]->pDiffusion->Dc.x*csat;
				app+=sizeof(double);
				
				*(double *)app=mpm[p]->pDiffusion->Dc.y*csat;
				app+=sizeof(double);
				
				if(threeD)
				{	*(double *)app=mpm[p]->pDiffusion->Dc.z*csat;
					app+=sizeof(double);
				}
			}
			else
 			{	*(double *)app=0.;
				app+=sizeof(double);
				
				*(double *)app=0.;
				app+=sizeof(double);
				
				if(threeD)
				{	*(double *)app=0.;
					app+=sizeof(double);
				}
			}
       }
		
        // total heat energy (Volume*energy) in J
        // energies in material point based on energy per unit mass
        // here need mass * U/(rho0 V0)
        // internal units are same as stress: N/m^2 cm^3/g = microJ/g = mJ/kg
		// note that rho*energy has units J/m^3 = N/m^2 (if rho in g/cm^3)
        if(mpmOrder[ARCH_HeatEnergy]=='Y')
        {   *(double *)app=1.0e-6*mpm[p]->mp*mpm[p]->GetHeatEnergy();
            app+=sizeof(double);
        }
		
		// element crossings since last archive - now cumulative
        if(mpmOrder[ARCH_ElementCrossings]=='Y')
        {	*(int *)app=mpm[p]->GetElementCrossings();
			app+=sizeof(int);
		}
		
		// here=initial angle z (degrees) while angle(above)=here-0.5*180*wxy/PI (degrees)
		//		Thus 0.5*180*wxy/PI = here-angle(above) or wxy = (PI/90)*(here-angle(above))
		// here=initial angle y (degrees) while angle(above)=here+0.5*180*wrot.xz/PI_CONSTANT (degrees)
		//		Thus 0.5*180*wxz/PI = -(here-angle(above)) or wxz = -(PI/90)*(here-angle(above))
		// here=initial angle x (degrees) while angle(above)=here-0.5*180.*wrot.yz/PI_CONSTANT; (degrees)
		//		Thus 0.5*180*wyz/PI = (here-angle(above)) or wyz = (PI/90)*(here-angle(above))
        if(mpmOrder[ARCH_RotStrain]=='Y')
		{	if(threeD)
			{	*(double *)app=mpm[p]->GetAnglez0InDegrees();
				app+=sizeof(double);
				*(double *)app=mpm[p]->GetAngley0InDegrees();
				app+=sizeof(double);
				*(double *)app=mpm[p]->GetAnglex0InDegrees();
				app+=sizeof(double);
			}
			else
        	{	*(double *)app=mpm[p]->GetAnglez0InDegrees();
				app+=sizeof(double);
			}
		}
		
        // padding
        if(mpmRecSize<recSize)
            app+=recSize-mpmRecSize;
        
        // reversing bytes?
        if(fmobj->GetReverseBytes())
        {   app-=recSize;
        
            // defaults
            app+=Reverse(app,sizeof(int));			// element
            app+=Reverse(app,sizeof(double));		// mass
            app+=Reverse(app,sizeof(short))+2;		// material ID
            app+=Reverse(app,sizeof(double));		// angle
            app+=Reverse(app,sizeof(double));		// thickness or dihedral
            app+=Reverse(app,sizeof(double));		// position
            app+=Reverse(app,sizeof(double));
			if(threeD) app+=Reverse(app,sizeof(double));
            app+=Reverse(app,sizeof(double));		// orig position
            app+=Reverse(app,sizeof(double));
			if(threeD) app+=Reverse(app,sizeof(double));
    
            // velocity (mm/sec)
            if(mpmOrder[ARCH_Velocity]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
				if(threeD) app+=Reverse(app,sizeof(double));
            }
    
            // stress 2D (in N/m^2)
            if(mpmOrder[ARCH_Stress]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
				if(threeD)
				{	app+=Reverse(app,sizeof(double));
					app+=Reverse(app,sizeof(double));
				}
            }

            // strain 2D (absolute)
            if(mpmOrder[ARCH_Strain]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
				if(threeD)
				{	app+=Reverse(app,sizeof(double));
					app+=Reverse(app,sizeof(double));
				}
            }
            
            // plastic strain (absolute)
            if(mpmOrder[ARCH_PlasticStrain]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
				if(threeD)
				{	app+=Reverse(app,sizeof(double));
					app+=Reverse(app,sizeof(double));
				}
            }
            
            // work energy (cumulative) in J
            if(mpmOrder[ARCH_WorkEnergy]=='Y')
                app+=Reverse(app,sizeof(double));
                    
            // temperature
            if(mpmOrder[ARCH_DeltaTemp]=='Y')
                app+=Reverse(app,sizeof(double));
            
            // total plastic energy
            if(mpmOrder[ARCH_PlasticEnergy]=='Y')
                app+=Reverse(app,sizeof(double));
                    
            // shear components
            if(mpmOrder[ARCH_ShearComponents]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
            }
    
            // total strain energy
            if(mpmOrder[ARCH_StrainEnergy]=='Y')
                app+=Reverse(app,sizeof(double));
                    
            // material history data on particle
            if(mpmOrder[ARCH_History]=='Y')
                app+=Reverse(app,sizeof(double));
			else if(mpmOrder[ARCH_History]!='N')
			{	if(mpmOrder[ARCH_History]&0x01) app+=Reverse(app,sizeof(double));
				if(mpmOrder[ARCH_History]&0x02) app+=Reverse(app,sizeof(double));
				if(mpmOrder[ARCH_History]&0x04) app+=Reverse(app,sizeof(double));
				if(mpmOrder[ARCH_History]&0x08) app+=Reverse(app,sizeof(double));
			}
                    
            // concentration and gradients
            if(mpmOrder[ARCH_Concentration]=='Y')
            {	app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
                app+=Reverse(app,sizeof(double));
				if(threeD)
					app+=Reverse(app,sizeof(double));
            }
			
            // total strain energy
            if(mpmOrder[ARCH_HeatEnergy]=='Y')
                app+=Reverse(app,sizeof(double));

            // element crossings
            if(mpmOrder[ARCH_ElementCrossings]=='Y')
                app+=Reverse(app,sizeof(int));
			
			// rotational strain
			if(mpmOrder[ARCH_RotStrain]=='Y')
             {	app+=Reverse(app,sizeof(double));
 				if(threeD)
				{	app+=Reverse(app,sizeof(double));
 					app+=Reverse(app,sizeof(double));
				}
            }
			
			// padding
            if(mpmRecSize<recSize)
                app+=recSize-mpmRecSize;
        }
		
		// write this particle (ofstream should buffer for us)
		try
		{	afile.write(aptr,blen);
			if(afile.bad())
				FileError("File error writing material point data",fname,"ArchiveData::ArchiveResults");
		}
		catch(CommonException err)
		{   // give up on hopefully temporary file problem
			cout << "# " << err.Message() << endl;
			cout << "# Will try to continue" << endl;
			afile.close();
			free(aptr);
			return;
		}
    }
    
	// clear material point record buffer
	free(aptr);
    
    // add the cracks
    nextCrack=firstCrack;
    while(nextCrack!=NULL)
    {	nextCrack->Archive(afile);
        nextCrack=(CrackHeader *)nextCrack->GetNextObject();
    }
    
    // close the file
	try
	{	afile.close();
		if(afile.bad())
			FileError("File error closing an archive file",fname,"ArchiveData::ArchiveResults");
	}
	catch(CommonException err)
	{   // give up on hopefully temporary file problem
		cout << "# " << err.Message() << endl;
		cout << "# Will try to continue" << endl;
	}
}
Пример #5
0
// Calculate J and K at crack tips
CustomTask *PropagateTask::StepCalculation(void)
{
    // if not needed, just exit
    if(!doPropCalcs) return nextTask;
	
	// particle extrapolation if needed
    if(doEnergyBalanceCalcs)
    {   totalPlastic = 0.;
        totalPotential = 0.;
        for(int p=0;p<nmpmsNR;p++)
        {   MPMBase *mpnt = mpm[p];
            
            // track total energies in J = N-m
            //	mp is g, stored energy is N/m^2 cm^3/g, vel is mm/sec
            // workEnergy in J =  1.0e-6*mp*mpm[p]->GetWorkEnergy()
            // plastic 1.0e-6*mp*mpm[p]->GetPlastEnergy()
            // external work 1.e-9*mpm[p]->GetExtWork()
            // kinetic energy 0.5e-9*mp*(vel.x*vel.x+vel.y*vel.y)
            
            // plastic energy per unit thickness (units of N) (only needed energy balance crack growth)
            double mp = mpnt->mp;
            totalPlastic += 1.0e-3*mp*mpnt->GetPlastEnergy()/mpnt->thickness();
            //totalPotential += 1.0e-3*(mp*mpnt->GetStrainEnergy()
            //                        + 0.5e-3*mp*(mpnt->vel.x*mpnt->vel.x+mpnt->vel.y*mpnt->vel.y)
            //                        - 1.e-3*mpnt->GetExtWork())/mpnt->thickness();
			throw "external work is no longer available";
        }
    }
    
    CrackHeader *nextCrack;
    CrackSegment *crkTip;
    double cSize;
    int i,inMat;
    Vector tipDir,growTo,grow;
    int tipElem;
	char isAlt[10];
    
    // loop over cracks
    nextCrack=firstCrack;
    while(nextCrack!=NULL)
    {	// each crack tip
        for(i=START_OF_CRACK;i<=END_OF_CRACK;i++)
        {   // find crack tip and direction
			nextCrack->CrackTipAndDirection(i,&crkTip,tipDir);
            
            // crack propagation
            inMat=crkTip->tipMatnum;
            if(inMat>0)
            {	// crack tip terms last two times propagated
                crkTip->potential[2]=crkTip->potential[1];
                crkTip->potential[1]=crkTip->potential[0];
                crkTip->potential[0]=totalPotential;
                crkTip->plastic[2]=crkTip->plastic[1];
                crkTip->plastic[1]=crkTip->plastic[0];
                crkTip->plastic[0]=totalPlastic;
                crkTip->clength[2]=crkTip->clength[1];
                crkTip->clength[1]=crkTip->clength[0];
                crkTip->clength[0]=nextCrack->Length();
            
                // see if it grows
				int shouldGo=theMaterials[inMat-1]->ShouldPropagate(crkTip,tipDir,nextCrack,fmobj->np,0);
				isAlt[0] = 0;
				if(shouldGo==GROWNOW)
				{	nextCrack->SetAllowAlternate(i,FALSE);
				}
				else if(nextCrack->GetAllowAlternate(i))
				{	shouldGo=theMaterials[inMat-1]->ShouldPropagate(crkTip,tipDir,nextCrack,fmobj->np,1);
					if(shouldGo==GROWNOW) strcpy(isAlt," (alt)");
				}
				if(shouldGo==GROWNOW)
                {   theResult=GROWNOW;
                    tipElem=crkTip->planeInElem-1;
                    if(fabs(tipDir.x)>fabs(tipDir.y))
                        cSize=theElements[tipElem]->xmax-theElements[tipElem]->xmin;
                    else
                        cSize=theElements[tipElem]->ymax-theElements[tipElem]->ymin;
                    grow.x=cellsPerPropagationStep*cSize*tipDir.x;
                    grow.y=cellsPerPropagationStep*cSize*tipDir.y;
					
					// adjust if crossing another crack
					double p = nextCrack->AdjustGrowForCrossing(&grow,crkTip);
					
					// crack number and tip
					archiver->IncrementPropagationCounter();
                    cout << "# propagation" << isAlt << " crack-tip " << nextCrack->GetNumber() << "-" << i;
					
					// summarize
					cout << " at t=" << 1000*mtime << " with J=Jtip+Jzone : " << 1000.*crkTip->Jint.z <<
							" = " << 1000.*crkTip->Jint.x << " + " << 1000.*(crkTip->Jint.z-crkTip->Jint.x) << endl;
                    
                    // if jump is .7 or more cells, make more than 1 segment
                    int iseg,numSegs = 1;
                    if(p*cellsPerPropagationStep>.7) numSegs= 2*(p*cellsPerPropagationStep+.25);
                    CrackSegment *newCrkTip;
                    for(iseg=1;iseg<=numSegs;iseg++)
                    {   growTo.x=crkTip->x+(double)iseg*grow.x/(double)numSegs;
                        growTo.y=crkTip->y+(double)iseg*grow.y/(double)numSegs;
                        if(fmobj->dflag[0]==4) growTo.y=0.;			// force cutting simulation to stay in cut plane at 0
                        newCrkTip=nextCrack->Propagate(growTo,(int)i,theMaterials[inMat-1]->tractionMat[0]);
                    }
                    crkTip = newCrkTip;
                    
					if(crkTip!=NULL)
					{	// check if crack speed is being controlled
						if(theMaterials[inMat-1]->ControlCrackSpeed(crkTip,propTime))
							nextPropTime=mtime+propTime;
						
						// crack tip heating (if activated)
						if(ConductionTask::active)
							conduction->StartCrackTipHeating(crkTip,grow,nextCrack->GetThickness());
					}
                }
                else
                {   // when no growth, restore previous growth results
                    crkTip->potential[0]=crkTip->potential[1];
                    crkTip->potential[1]=crkTip->potential[2];
                    crkTip->plastic[0]=crkTip->plastic[1];
                    crkTip->plastic[1]=crkTip->plastic[2];
                    crkTip->clength[0]=crkTip->clength[1];
                    crkTip->clength[1]=crkTip->clength[2];
                }
            }
        }

        // next crack
        nextCrack=(CrackHeader *)nextCrack->GetNextObject();
    }
    
    return nextTask;
}
Пример #6
0
// Calculate J and K at crack tips
CustomTask *PropagateTask::StepCalculation(void)
{
    // if not needed, just exit
    if(!doPropCalcs) return nextTask;
	
    CrackHeader *nextCrack;
    CrackSegment *crkTip;
    double cSize;
    int i,inMat;
    Vector tipDir,growTo,grow;
    int tipElem;
	char isAlt[10];
    
    // loop over cracks
    nextCrack=firstCrack;
    while(nextCrack!=NULL)
    {	// each crack tip
        for(i=START_OF_CRACK;i<=END_OF_CRACK;i++)
        {   // find crack tip and direction
			nextCrack->CrackTipAndDirection(i,&crkTip,tipDir);
            
            // crack propagation
            inMat=crkTip->tipMatnum;
            if(inMat>0)
            {	// see if it grows
				int shouldGo=theMaterials[inMat-1]->ShouldPropagate(crkTip,tipDir,nextCrack,fmobj->np,0);
				isAlt[0] = 0;
				if(shouldGo==GROWNOW)
				{	nextCrack->SetAllowAlternate(i,false);
				}
				else if(nextCrack->GetAllowAlternate(i))
				{	shouldGo=theMaterials[inMat-1]->ShouldPropagate(crkTip,tipDir,nextCrack,fmobj->np,1);
					if(shouldGo==GROWNOW) strcpy(isAlt," (alt)");
				}
				if(shouldGo==GROWNOW)
                {   theResult=GROWNOW;
                    tipElem=crkTip->planeElemID();
                    if(fabs(tipDir.x)>fabs(tipDir.y))
                        cSize=theElements[tipElem]->xmax-theElements[tipElem]->xmin;
                    else
                        cSize=theElements[tipElem]->ymax-theElements[tipElem]->ymin;
                    grow.x=cellsPerPropagationStep*cSize*tipDir.x;
                    grow.y=cellsPerPropagationStep*cSize*tipDir.y;
					
					// adjust if crossing another crack - adjusts grow is need and returns resulting relative change (in p)
					double p = nextCrack->AdjustGrowForCrossing(&grow,crkTip,cSize,&tipDir);
					
					// crack number and tip
					archiver->IncrementPropagationCounter();
                    cout << "# propagation" << isAlt << " crack-tip " << nextCrack->GetNumber() << "-" << i;
					
					// summarize
					cout << " at t=" << mtime*UnitsController::Scaling(1.e3)
						<< " with J=Jtip+Jzone : " << crkTip->Jint.z*UnitsController::Scaling(1.e-3)
						<< " = " << crkTip->Jint.x*UnitsController::Scaling(1.e-3)
						<< " + " << (crkTip->Jint.z-crkTip->Jint.x)*UnitsController::Scaling(1.e-3) << endl;
                    
                    // if jump is .7 or more cells, divide propagation into multiple segments
                    int iseg,numSegs = 1;
                    if(p*cellsPerPropagationStep>.7) numSegs= (int)(2*(p*cellsPerPropagationStep+.25));
                    CrackSegment *newCrkTip = NULL;
                    for(iseg=1;iseg<=numSegs;iseg++)
                    {   growTo.x=crkTip->x+(double)iseg*grow.x/(double)numSegs;
                        growTo.y=crkTip->y+(double)iseg*grow.y/(double)numSegs;
                        newCrkTip=nextCrack->Propagate(growTo,(int)i,theMaterials[inMat-1]->tractionMat[0]);
                    }
                    crkTip = newCrkTip;
                    
					if(crkTip!=NULL)
					{	// check if crack speed is being controlled
						if(theMaterials[inMat-1]->ControlCrackSpeed(crkTip,propTime))
							nextPropTime=mtime+propTime;
						
						// crack tip heating (if activated)
						if(ConductionTask::active)
							conduction->StartCrackTipHeating(crkTip,grow,nextCrack->GetThickness());
					}
                }
            }
        }

        // next crack
        nextCrack=(CrackHeader *)nextCrack->GetNextObject();
    }
    
    return nextTask;
}