Skip to content
Snippets Groups Projects
updateNodes.jl 16.9 KiB
Newer Older
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
# Amira Abdel-Rahman
# (c) Massachusetts Institute of Technology 2020

# BASED ON https://github.com/jonhiller/Voxelyze


function updateNodes!(dt,currentTimeStep,N_position, N_restrained,N_displacement,N_angle,N_currPosition,N_linMom,N_angMom,
        N_intForce,N_intMoment,N_force,N_fixedDisplacement,N_moment,N_orient,N_edgeID,N_edgeFirst,N_material,N_poissonStrain,
        E_intForce1,E_intMoment1,E_intForce2,E_intMoment2,E_axis, E_strain,E_material)

    index = (blockIdx().x - 1) * blockDim().x + threadIdx().x
    stride = blockDim().x * gridDim().x
    ## @cuprintln("thread $index, block $stride")
    N,M=size(N_edgeID)
    for i = index:stride:N
        
        isFloorEnabled=floorEnabled();#todo make these arguments ??
        
        # @inbounds if lengthVector3(Vector3(convert(Float64,N_displacement[i].x), 
        #             convert(Float64,N_displacement[i].y),convert(Float64,N_displacement[i].z))) >1000.0 #todo ?? change this according to ratio
        #     # @cuprintln("DIVERGEDNODE!!!!!!!!!!")
        #     return 
        # end
        
        
        
        @inbounds if N_restrained[i]
            @inbounds N_linMom[i]=Vector3(0,0,0)
            @inbounds N_angMom[i]=Vector3(0,0,0)
            @inbounds if(N_material[i].poisson)
                @inbounds N_poissonStrain[i]=strain(i,N_material[i].poisson,i, N_edgeID, N_edgeFirst, E_axis, E_strain, E_material, N_restrained[i], N_material[i])
            end
            return
        elseif N_fixedDisplacement[i].x != 0.0 || N_fixedDisplacement[i].y != 0.0  ||  N_fixedDisplacement[i].z != 0.0
            @inbounds N_linMom[i]=Vector3(0,0,0)
            @inbounds N_angMom[i]=Vector3(0,0,0)
            @inbounds if(N_material[i].poisson)
                @inbounds N_poissonStrain[i]=strain(i,N_material[i].poisson,i, N_edgeID, N_edgeFirst, E_axis, E_strain, E_material, N_restrained[i], N_material[i])
            end
            @inbounds translate=externalDisplacement(currentTimeStep,N_position,N_fixedDisplacement[i])
            @inbounds N_currPosition[i]=N_currPosition[i]+translate
            @inbounds N_displacement[i]=N_displacement[i]+translate

        else
            
            for j in 1:M
                @inbounds if (N_edgeID[i,j]!=-1)
                    #@cuprintln("i $i, j $j, N_edgeID[i,j] $temp")
                    @inbounds N_intForce[i]=ifelse(N_edgeFirst[i,j], N_intForce[i]+E_intForce1[N_edgeID[i,j]], N_intForce[i]+E_intForce2[N_edgeID[i,j]] )
                    @inbounds N_intMoment[i]=ifelse(N_edgeFirst[i,j], N_intMoment[i]+E_intMoment1[N_edgeID[i,j]], N_intMoment[i]+E_intMoment2[N_edgeID[i,j]] )
                end
            
            end
            
            FloorStaticFriction=false; 
            
            prec=1e8
            #get properties
            @inbounds E=roundd(N_material[i].E,prec)
            @inbounds nomSize=roundd(N_material[i].nomSize,prec)
            @inbounds mass=roundd(N_material[i].mass,prec)
            @inbounds massInverse=roundd(N_material[i].massInverse,prec)
            
            @inbounds curForce = force(i,N_intForce[i],N_orient[i],N_force[i],N_position[i],currentTimeStep,N_material[i],N_linMom[i])

            fricForce = Vector3(curForce.x,curForce.y,curForce.z);
            if (isFloorEnabled)
                @inbounds curForce,FloorStaticFriction=floorForce!(dt,curForce,N_currPosition[i],
                    Vector3(N_linMom[i].x,N_linMom[i].y ,N_linMom[i].z),FloorStaticFriction,N_material[i])
                
            end
            
            fricForce = curForce-fricForce;

            # if(i==25)
                # x=N_intForce[i].x*1e6
                # y=N_intForce[i].y*1e6
                # z=N_intForce[i].z*1e6
                # @cuprintln("N_intForce[i] x $x 1e-6, y $y 1e-6, z $z 1e-6")

                # x=curForce.x*1e6
                # y=curForce.y*1e6
                # z=curForce.z*1e6
                # @cuprintln("curForce x $x 1e-6, y $y 1e-6, z $z 1e-6")

                # x=N_linMom[i].x*1e6
                # y=N_linMom[i].y*1e6
                # z=N_linMom[i].z*1e6
                # @cuprintln("N_linMom[i] x $x 1e-6, y $y 1e-6, z $z 1e-6")

                # x=translate.x*1e0
                # y=translate.y*1e0
                # z=translate.z*1e0
                # @cuprintln("translate x $x, y $y, z $z")
                # @cuprintln("")
            # end


            # x=N_orient[i].x*1e6
            # y=N_orient[i].y*1e6
            # z=N_orient[i].z*1e6
            # @cuprintln("N_orient[i] x $x 1e-6, y $y 1e-6, z $z 1e-6")

            # x=N_linMom[i].x*1e6
            # y=N_linMom[i].y*1e6
            # z=N_linMom[i].z*1e6
            # @cuprintln("N_linMom[i] x $x 1e-6, y $y 1e-6, z $z 1e-6")

            # x=curForce.x*1e6
            # y=curForce.y*1e6
            # z=curForce.z*1e6
            # @cuprintln("curForce x $x 1e-6, y $y 1e-6, z $z 1e-6")

            # @cuprintln("dt $dt")
            # @cuprintln("massInverse $massInverse")
            
            
            #########################################
            
            # @inbounds N_intForce[i]=Vector3(0,0,0) #??
        
            
            @inbounds N_linMom[i]=N_linMom[i]+curForce*Vector3(dt,dt,dt) #todo make sure right
            @inbounds translate=N_linMom[i]*Vector3((dt*massInverse),(dt*massInverse),(dt*massInverse)) # ??massInverse

            
            
            ############################
            
            
            #we need to check for friction conditions here (after calculating the translation) and stop things accordingly
            @inbounds if (isFloorEnabled && floorPenetration( convert(Float64,N_currPosition[i].x),convert(Float64,N_currPosition[i].y),N_material[i].nomSize)>= 0.0 )#we must catch a slowing voxel here since it all boils down to needing access to the dt of this timestep.
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
                work =convert(Float64,fricForce.x*translate.x + fricForce.z*translate.z); #F dot disp
                @inbounds hKe = 0.5*massInverse*convert(Float64,(N_linMom[i].x*N_linMom[i].x + N_linMom[i].z*N_linMom[i].z)); #horizontal kinetic energy

                if((hKe + work) <= 0.0) 
                    FloorStaticFriction=true; #this checks for a change of direction according to the work-energy principle
                end

                if(FloorStaticFriction)
                    #if we're in a state of static friction, zero out all horizontal motion
                    N_linMom[i]=Vector3(0.0 ,convert(Float64,N_linMom[i].y) ,0.0)
                    translate=Vector3(0.0 ,convert(Float64,translate.y) ,0.0)
                end
            else
                FloorStaticFriction=false
            end

            
            
            @inbounds N_currPosition[i]=N_currPosition[i]+translate
            @inbounds N_displacement[i]=N_displacement[i]+translate
            
            
            # Rotation
            @inbounds curMoment = moment(N_intMoment[i],N_orient[i],N_moment[i],N_material[i],N_angMom[i]) 
            
            @inbounds N_intMoment[i]=Vector3(0,0,0) # do i really need it?
            @inbounds N_intForce[i]=Vector3(0,0,0) # do i really need it?
            
            @inbounds N_angMom[i]=N_angMom[i]+curMoment*Vector3(dt,dt,dt)
            
            @inbounds momentInertiaInverse=N_material[i].momentInertiaInverse
            
            @inbounds temp=FromRotationVector(N_angMom[i]*Vector3((dt*momentInertiaInverse),(dt*momentInertiaInverse),(dt*momentInertiaInverse)))

            
            @inbounds N_orient[i]=multiplyQuaternions(temp,N_orient[i])

            @inbounds N_angle[i]=ToRotationVector(N_orient[i])

            # x=N_orient[i].x*1e0
            # y=N_orient[i].y*1e0
            # z=N_orient[i].z*1e0
            # @cuprintln("N_orient[i] x $x, y $y, z $z ")
            # @cuprintln("momentInertiaInverse $momentInertiaInverse")

            # if (ext){
            #     double size = mat->nominalSize();
            #     if (ext->isFixed(X_TRANSLATE)) {pos.x = ix*size + ext->translation().x; linMom.x=0;}
            #     if (ext->isFixed(Y_TRANSLATE)) {pos.y = iy*size + ext->translation().y; linMom.y=0;}
            #     if (ext->isFixed(Z_TRANSLATE)) {pos.z = iz*size + ext->translation().z; linMom.z=0;}
            #     if (ext->isFixedAnyRotation()){ //if any rotation fixed, all are fixed
            #         if (ext->isFixedAllRotation()){
            #             orient = ext->rotationQuat();
            #             angMom = Vec3D<double>();
            #         }
            #         else { //partial fixes: slow!
            #             Vec3D<double> tmpRotVec = orient.ToRotationVector();
            #             if (ext->isFixed(X_ROTATE)){ tmpRotVec.x=0; angMom.x=0;}
            #             if (ext->isFixed(Y_ROTATE)){ tmpRotVec.y=0; angMom.y=0;}
            #             if (ext->isFixed(Z_ROTATE)){ tmpRotVec.z=0; angMom.z=0;}
            #             orient.FromRotationVector(tmpRotVec);
            #         }
            #     }
            # }

            # if(i==17)
            #     x=(N_currPosition[i].x-0.004)*1e6
            #     y=N_currPosition[i].y*1e6
            #     z=N_currPosition[i].z*1e6
            #     @cuprintln("pos 17 x $x 1e-6, y $y 1e-6, z $z 1e-6")
            #     @cuprintln("")
            # end

            # if(i==25)
                # x=(N_currPosition[i].x)*1e6
                # y=N_currPosition[i].y*1e6
                # z=N_currPosition[i].z*1e6
                # @cuprintln("pos 25 x $x 1e-6, y $y 1e-6, z $z 1e-6")
                # @cuprintln("")
            # end

            # if(i==41)
            #     x=curForce.x*1e6
            #     y=curForce.y*1e6
            #     z=curForce.z*1e6
            #     @cuprintln("curForce x $x 1e-6, y $y 1e-6, z $z 1e-6")

                # x=(N_currPosition[i].x-0.004)*1e6
                # y=N_currPosition[i].y*1e6
                # z=N_currPosition[i].z*1e6
                # @cuprintln("pos x $x 1e-6, y $y 1e-6, z $z 1e-6")
                # @cuprintln("")
            # end
        
            ####poisson
            @inbounds if(N_material[i].poisson)
                @inbounds N_poissonStrain[i]=strain(i,N_material[i].poisson,i, N_edgeID, N_edgeFirst, E_axis, E_strain, E_material, N_restrained[i], N_material[i])
            end
        end
    end
    return
end


function run_updateNodes!(dt,currentTimeStep,N_position, N_restrained,N_displacement, N_angle,N_currPosition,
        N_linMom,N_angMom,N_intForce,N_intMoment,N_force,N_fixedDisplacement,N_moment,N_orient,N_edgeID,N_edgeFirst,N_material,N_poissonStrain,
        E_intForce1,E_intMoment1,E_intForce2,E_intMoment2,E_axis, E_strain,E_material)
    N=length(N_intForce)
    numblocks = ceil(Int, N/256)
    CUDA.@sync begin
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
        @cuda threads=256 blocks=numblocks updateNodes!(dt,currentTimeStep,N_position, N_restrained,N_displacement, 
            N_angle,N_currPosition,N_linMom,N_angMom,N_intForce,N_intMoment,N_force,N_fixedDisplacement,N_moment,N_orient,N_edgeID,N_edgeFirst,N_material,N_poissonStrain,
            E_intForce1,E_intMoment1,E_intForce2,E_intMoment2,E_axis, E_strain,E_material)
    end
end


############################

function strain(i,poissonStrain,id,N_edgeID,N_edgeFirst, E_axis, E_strain,E_material,fixed,mat)
	
	###if no connections in the positive and negative directions of a particular axis, strain is zero
	###if one connection in positive or negative direction of a particular axis, strain is that strain - ?? and force or constraint?
	###if connections in both the positive and negative directions of a particular axis, strain is the average. 
	
    # intStrRet= [0.0, 0.0, 0.0] ###intermediate strain return value. axes according to linkAxis enum
	# numBondAxis = [0,0,0]; ###number of bonds in this axis (0,1,2). axes according to linkAxis enum
    # tension = [false,false,false];

    intStrRet1=0.0
    intStrRet2=0.0
    intStrRet3=0.0

    numBondAxis1=0.0
    numBondAxis2=0.0
    numBondAxis3=0.0

    tension1=false
    tension2=false
    tension3=false

    N,M=size(N_edgeID)
    for j in 1:M
        @inbounds linkID=N_edgeID[id,j]
        # @cuprintln("id $id, j $j, linkID $linkID")
        if (linkID!=-1)
            # if (E_strain[j]!=0.0)
                @inbounds axis= normalizeVector3(E_axis[linkID])
                @inbounds strain1=axialStrain( N_edgeFirst[id,j],E_strain[linkID],E_material[linkID])
                # if (E_strain[j]!=0.0)
                #     @cuprint("strain1 $strain1")
                # end
                x= abs(convert(Float64,axis.x))*strain1 #todo change for general axis
                y= abs(convert(Float64,axis.y))*strain1 #todo change for general axis
                z= abs(convert(Float64,axis.z))*strain1 #todo change for general axis
                if (axis.x!=0.0)
                    intStrRet1+=x
                    numBondAxis1+=1
                    # if(i==32)
                    #     @cuprintln("strain1 x $(strain1)")
                    # end
                end
                if (axis.y!=0.0)
                    intStrRet2+=y
                    numBondAxis2+=1
                end
                if (axis.z!=0.0)
                    intStrRet3+=z
                    numBondAxis3+=1
                end
            # end
        end
    end
    # @cuprintln("intStrRet 11 x $(intStrRet1*1e6) *1e-6, y $(intStrRet2*1e6) *1e-6, z $(intStrRet3*1e6) *1e-6")
    # for i =1:3
        if (numBondAxis1>1.0) 
            intStrRet1=intStrRet1 /numBondAxis1 ###average
        end
        if (poissonStrain)
            tension1 = ((numBondAxis1==2.0) || (fixed&&numBondAxis1==1.0))
                #(ext && (numBondAxis[i]==1 && (ext.isFixed((dofComponent)(1<<i)) || ext.force()[i] != 0)))); #if both sides pulling, or just one side and a fixed or forced voxel...
        end

        if (numBondAxis2>1.0) 
            intStrRet2=intStrRet2 /numBondAxis2 ###average
        end
        if (poissonStrain)
            tension2 = ((numBondAxis2==2.0) || (fixed&&numBondAxis2==1.0))
                #(ext && (numBondAxis[i]==1 && (ext.isFixed((dofComponent)(1<<i)) || ext.force()[i] != 0)))); #if both sides pulling, or just one side and a fixed or forced voxel...
        end

        if (numBondAxis3>1.0) 
            intStrRet3=intStrRet3 /numBondAxis3 ###average
        end
        if (poissonStrain)
            tension3 = ((numBondAxis3==2.0) || (fixed&&numBondAxis3==1.0))
                #(ext && (numBondAxis[i]==1 && (ext.isFixed((dofComponent)(1<<i)) || ext.force()[i] != 0)))); #if both sides pulling, or just one side and a fixed or forced voxel...
        end
    # end

    # if(i==32)
    #     @cuprintln("intStrRet 1 x $(intStrRet1) , y $(intStrRet2) , z $(intStrRet3)")
    #     @cuprintln("numBondAxis x $(numBondAxis1) , y $(numBondAxis2) , z $(numBondAxis3) ")
    # end

	if (poissonStrain)
		if (!(tension1 && tension2 && tension3 )) ###if at least one isn't in tension
			add = 0.0;
            # for i =1:3
                if (tension1) 
                    add=add+intStrRet1
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
                end
                if (tension2) 
                    add=add+intStrRet2
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
                end
                if (tension3) 
                    add=add+intStrRet3
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed
                end
            # end
            # @cuprintln("add x $(add*1e6)")
            # @cuprintln("mat.nu x $(mat.nu)")
            # value =  pow((1.0 + add),(-mat.nu))-1.0 #((1.0 + add)^(-mat.nu)) - 1.0;
            value = CUDA.pow( 1.0 + add, -mat.nu) - 1.0;
Amira Abdel-Rahman's avatar
Amira Abdel-Rahman committed

            # if(i==32)
            #     @cuprintln("value x $(value)")
            #     @cuprintln("mat.nu x $(mat.nu)")
            #     @cuprintln("add x $(add)")
            # end


            # value =((1.0 + add)^(-roundd(mat.nu,10e5))) - 1.0;
            # @cuprintln("value x $(value*1e6)")
            # value=0.0
            # for i =1:3
                if (!tension1) 
                    intStrRet1=value;
                end
                if (!tension2) 
                    intStrRet2=value;
                end
                if (!tension3) 
                    intStrRet3=value;
                end
            # end   
        end
    end

    # if(i==32)
    #     @cuprintln("intStrRet 2 x $(intStrRet1*1e6) *1e-6, y $(intStrRet2*1e6) *1e-6, z $(intStrRet3*1e6) *1e-6")
    # end

    intStrRet= Vector3(intStrRet1,intStrRet2,intStrRet3); ###intermediate strain return value. axes according to linkAxis enum
    # @cuprintln("intStrRet x $(intStrRet1*1e6) *1e-6, y $(intStrRet2*1e6) *1e-6, z $(intStrRet3*1e6) *1e-6")
    # @cuprintln("numBondAxis x $(numBondAxis1) , y $(numBondAxis2) , z $(numBondAxis3) ")
    # if tension1
    #     tension1=1.0
    # else
    #     tension1=0.0
    # end
    # if tension2
    #     tension2=1.0
    # else
    #     tension2=0.0
    # end
    # if tension3
    #     tension3=1.0
    # else
    #     tension3=0.0
    # end
    # @cuprintln("tension x $(tension1) , y $(tension2) , z $(tension3) ")
	return intStrRet
end

function axialStrain( positiveEnd,strain,mat)
    #strainRatio = pVPos->material()->E/pVNeg->material()->E;
    strainRatio=convert(Float64,mat.strainRatio)
    # positiveEnd=true
    return positiveEnd ? 2.0 *strain*strainRatio/(1.0+strainRatio) : 2.0*strain/(1.0+strainRatio)
end