コード例 #1
0
ファイル: MatPtLoadBC.cpp プロジェクト: pbena/nairn-mpm-fea
// reverse active linear loads. Leave rest alone
// input is analysis time in seconds
// if LINEAR_VALUE, set finalTime to time when load returns to zero
MatPtLoadBC *MatPtLoadBC::ReverseLinearLoad(double bctime,double *finalTime,bool holdFirst)
{
    switch(style)
    {	case LINEAR_VALUE:
            if(bctime>=GetBCFirstTime())
			{   SetBCOffset(BCValue(bctime));
                if(holdFirst)
				{	// change to offset (set above) with zero slope to get a constant load
                    holdValue = GetBCValue();
                    holding = true;
                    SetBCValue(0.);
                }
                else
				{	// get unloading slope (units/time)
					double bcvalue = holding ? -holdValue : -GetBCValue() ;
					
					// change to offset+(slope)*(time-ftime) by setting offset (above), new slope, and new first time 
					SetBCValueCU(bcvalue);
                    SetBCFirstTimeCU(bctime);
                    
					// find time when BC returns to zero
                    // new BC is offset+value*(mstime-ftime), which is zero when mstime = ftime-offset/value
                    *finalTime = GetBCFirstTime() - GetBCOffset()/GetBCValue();
                }
                
            }
            break;
        default:
            break;
    }
    return (MatPtLoadBC *)GetNextObject();
}
コード例 #2
0
ファイル: MatPtLoadBC.cpp プロジェクト: bbanerjee/ParSim
// increment external load on a particle
// input is analysis time in seconds
MatPtLoadBC *MatPtLoadBC::AddMPLoad(double bctime)
{
	if(style!=SILENT)
	{	double mstime=1000.*bctime;
		Vector *pFext=mpm[ptNum-1]->GetPFext();
		
		if(direction==X_DIRECTION)
			 pFext->x+=BCValue(mstime);
		else if(direction==Y_DIRECTION)
			 pFext->y+=BCValue(mstime);
		else
			 pFext->z+=BCValue(mstime);
	}
	else
	{	double mp=mpm[ptNum-1]->mp;												// in g
		int matnum=mpm[ptNum-1]->MatID();
		double cd=theMaterials[matnum]->WaveSpeed(FALSE,mpm[ptNum-1]);			// in mm/sec (2D or isotropic only)
		double cs=theMaterials[matnum]->ShearWaveSpeed(FALSE,mpm[ptNum-1]);		// in mm/sec
		Vector pVel=mpm[ptNum-1]->vel;
		Vector *pFext=mpm[ptNum-1]->GetPFext();
		
		// get forces in g-mm/sec^2
		if(direction==X_DIRECTION)
		{	pFext->x-=mp*cd*pVel.x/(2.*mpmgrid.partx);
			pFext->y-=mp*cs*pVel.y/(2.*mpmgrid.partx);
			pFext->z-=mp*cs*pVel.z/(2.*mpmgrid.partx);
		}
		else if(direction==Y_DIRECTION)
		{	pFext->x-=mp*cs*pVel.x/(2.*mpmgrid.party);
			pFext->y-=mp*cd*pVel.y/(2.*mpmgrid.party);
			pFext->z-=mp*cs*pVel.z/(2.*mpmgrid.party);
		}
		else
		{	pFext->x-=mp*cs*pVel.x/(2.*mpmgrid.partz);
			pFext->y-=mp*cs*pVel.y/(2.*mpmgrid.partz);
			pFext->z-=mp*cd*pVel.z/(2.*mpmgrid.partz);
		}
	}
		
    return (MatPtLoadBC *)GetNextObject();
}
コード例 #3
0
ファイル: MatPtLoadBC.cpp プロジェクト: pbena/nairn-mpm-fea
// hold active linear loads at current values. Leave rest alone
// input is analysis time in seconds
MatPtLoadBC *MatPtLoadBC::MakeConstantLoad(double bctime)
{
    switch(style)
    {	case LINEAR_VALUE:
            if(bctime>=GetBCFirstTime())
            {	style=CONSTANT_VALUE;
				SetBCValueCU(BCValue(bctime));
            }
            break;
        default:
            break;
    }
    return (MatPtLoadBC *)GetNextObject();
}
コード例 #4
0
ファイル: MatPtLoadBC.cpp プロジェクト: bbanerjee/ParSim
// hold active linear loads at current values. Leave rest alone
// input is analysis time in seconds
MatPtLoadBC *MatPtLoadBC::MakeConstantLoad(double bctime)
{
	double mstime=1000.*bctime;
	
    switch(style)
    {	case LINEAR_VALUE:
            if(mstime>=ftime)
            {	style=CONSTANT_VALUE;
                value=BCValue(mstime);
            }
            break;
        default:
            break;
    }
    return (MatPtLoadBC *)GetNextObject();
}
コード例 #5
0
ファイル: MatPtLoadBC.cpp プロジェクト: bbanerjee/ParSim
// reverse active linear loads. Leave rest alone
// input is analysis time in seconds
// if LINEAR_VALUE, set finalTime to time when load returns to zero
MatPtLoadBC *MatPtLoadBC::ReverseLinearLoad(double bctime,double *finalTime)
{
	double mstime=1000.*bctime;
	
    switch(style)
    {	case LINEAR_VALUE:
            if(mstime>=ftime)
			{   offset=BCValue(mstime);
                value=-value;
                ftime=mstime;
				// new BC is offset+value*(mstime-ftime), which is zero when mstime = ftime-offset/value
				*finalTime = 0.001*(ftime - offset/value);
            }
            break;
        default:
            break;
    }
    return (MatPtLoadBC *)GetNextObject();
}
コード例 #6
0
ファイル: MatPtFluxBC.cpp プロジェクト: pbena/nairn-mpm-fea
// increment external load on a particle
// input is analysis time in seconds
// (only called when diffusion is active)
MatPtFluxBC *MatPtFluxBC::AddMPFlux(double bctime)
{
    // condition value is g/(mm^2-sec), Divide by rho*csat to get potential flux in mm/sec
	// find this flux and then add (times area) to get mm^3-potential/sec
	MPMBase *mpmptr = mpm[ptNum-1];
    MaterialBase *matptr = theMaterials[mpmptr->MatID()];
	
	// Flux is a scalar and we need int_(face) F Ni(x) dA
	// Since F is constant, only need integral which is done by CPDI methods
	//		which has be generalized to work for GIMP too
	// We use X_DIRECTION for bcDIR for efficiency. For Silent BC, change to
	//      Normal direction to all caculation of n
	Vector fluxMag;
	ZeroVector(&fluxMag);
    int bcDir=X_DIRECTION;
	
	if(style==SILENT)
	{	TransportProperties t;
		matptr->GetTransportProps(mpmptr,fmobj->np,&t);
		Tensor *D = &(t.diffusionTensor);
        
        // D in mm^2/sec, Dc in 1/mm
		if(fmobj->IsThreeD())
		{	fluxMag.x = D->xx*mpmptr->pDiffusion[gGRADx] + D->xy*mpmptr->pDiffusion[gGRADy] + D->xz*mpmptr->pDiffusion[gGRADz];
			fluxMag.y = D->xy*mpmptr->pDiffusion[gGRADx] + D->yy*mpmptr->pDiffusion[gGRADy] + D->yz*mpmptr->pDiffusion[gGRADz];
			fluxMag.z = D->xz*mpmptr->pDiffusion[gGRADx] + D->yz*mpmptr->pDiffusion[gGRADy] + D->zz*mpmptr->pDiffusion[gGRADz];
		}
		else
		{	fluxMag.x = D->xx*mpmptr->pDiffusion[gGRADx] + D->xy*mpmptr->pDiffusion[gGRADy];
			fluxMag.y = D->xy*mpmptr->pDiffusion[gGRADx] + D->yy*mpmptr->pDiffusion[gGRADy];
		}
        bcDir = N_DIRECTION;
	}
	else if(direction==EXTERNAL_FLUX)
	{	// csatrho = rho0 V0 csat/V (units g/mm^3)
		double csatrho = mpmptr->GetRho()*mpmptr->GetConcSaturation()/mpmptr->GetRelativeVolume();
		fluxMag.x = BCValue(bctime)/csatrho;
	}
	else
    {   // coupled surface flux and ftime is bath concentration
		// time variable (t) is replaced by c-cbath, where c is the particle potential and cbath is bath potential
		varTime = mpmptr->pPreviousConcentration-GetBCFirstTime();
		GetPosition(&varXValue,&varYValue,&varZValue,&varRotValue);
		double currentValue = fabs(scale*function->Val());
		if(varTime>0.) currentValue=-currentValue;
		
		// csatrho = rho0 V0 csat/V (units g/mm^3)
		double csatrho = mpmptr->GetRho()*mpmptr->GetConcSaturation()/mpmptr->GetRelativeVolume();
		fluxMag.x = currentValue/csatrho;
	}
	
	// get corners and direction from material point
	int cElem[4],numDnds;
	Vector corners[4],tscaled;
	double ratio = mpmptr->GetTractionInfo(face,bcDir,cElem,corners,&tscaled,&numDnds);
	
    // compact CPDI nodes into list of nodes (nds) and final shape function term (fn)
    // May need up to 8 (in 3D) for each of the numDnds (2 in 2D or 4 in 3D)
    int nds[8*numDnds+1];
    double fn[8*numDnds+1];
    int numnds = CompactCornerNodes(numDnds,corners,cElem,ratio,nds,fn);
	
    // add force to each node
	int i;
    for(i=1;i<=numnds;i++)
		diffusion->AddFluxCondition(nd[nds[i]],DotVectors(&fluxMag,&tscaled)*fn[i],false);
	
    return (MatPtFluxBC *)GetNextObject();
}