Exemplo n.º 1
0
IRResultType Delamination :: initializeFrom(InputRecord *ir)
{
    IRResultType result;                   // Required by IR_GIVE_FIELD macro

    result = EnrichmentItem :: initializeFrom(ir);
    if ( result != IRRT_OK ) return result;

    // Compute the delamination xi-coord
    IR_GIVE_FIELD(ir, this->interfaceNum, _IFT_Delamination_interfacenum); // interface number from the bottom
    IR_GIVE_FIELD(ir, this->crossSectionNum, _IFT_Delamination_csnum);

    LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveDomain()->giveCrossSection(this->crossSectionNum) );
    if ( layeredCS == NULL ) {
        OOFEM_WARNING("Delamination EI requires a valid layered cross section number input: see record '%s'.", _IFT_Delamination_csnum);
        return IRRT_BAD_FORMAT;
    } else if ( this->interfaceNum.giveSize() < 1 || this->interfaceNum.giveSize() > 2 ) {
        OOFEM_WARNING("Size of record 'interfacenum' must be 1 or 2");
        return IRRT_BAD_FORMAT;
    }

    // check that interface numbers are valid
    interfaceNum.printYourself("interface num");
    for ( int i = 1; i <= this->interfaceNum.giveSize(); i++ ) {
        if ( this->interfaceNum.at(i) < 1 || this->interfaceNum.at(i) >= layeredCS->giveNumberOfLayers() ) {
            OOFEM_WARNING( "Cross section does not contain the interface number (%d) specified in the record '%s' since number of layers is %d.", this->interfaceNum.at(i), _IFT_Delamination_interfacenum, layeredCS->giveNumberOfLayers() );
            return IRRT_BAD_FORMAT;
        }
    }

    // compute xi-coord of the delamination
    this->delamXiCoord = -1.0;
    double totalThickness = layeredCS->give(CS_Thickness, FloatArray(), NULL, false); // no position available
    for ( int i = 1; i <= this->interfaceNum.at(1); i++ ) {
        this->delamXiCoord += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
        this->xiBottom += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
    }

    if ( this->interfaceNum.giveSize() == 2 ) {
        if ( this->interfaceNum.at(1) >= this->interfaceNum.at(2) ) {
            OOFEM_WARNING("second intercfacenum must be greater than the first one");
            return IRRT_BAD_FORMAT;
        }
        for ( int i = 1; i <= this->interfaceNum.at(2); i++ ) {
            this->xiTop += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
        }
    } else {
        this->xiTop = 1.0; // default is the top surface
    }


    IR_GIVE_OPTIONAL_FIELD(ir, this->matNum, _IFT_Delamination_CohesiveZoneMaterial);
    if ( this->matNum > 0 ) {
        this->mat = this->giveDomain()->giveMaterial(this->matNum);
    }

    return IRRT_OK;
}
Exemplo n.º 2
0
void StructuralMaterialEvaluator :: solveYourself()
{
    Domain *d = this->giveDomain(1);

    MaterialMode mode = _3dMat;
    FloatArray initialStrain(6);
    gps.clear();
    gps.reserve(d->giveNumberOfMaterialModels());
    for ( int i = 1; i <= d->giveNumberOfMaterialModels(); i++ ) {
        std :: unique_ptr< GaussPoint > gp = std::make_unique<GaussPoint>(nullptr, i, FloatArray(0), 1, mode);
        gps.emplace_back( std :: move(gp) );
        // Initialize the strain vector;
        StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( d->giveMaterial(i)->giveStatus( gps[i-1].get() ) );
        status->letStrainVectorBe(initialStrain);
    }

    std :: string outname = this->giveOutputBaseFileName() + ".matdata";
    this->outfile.open( outname.c_str() );

    this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer);

    TimeStep *tStep = giveNextStep();

    // Note, strain == strain-rate (kept as strain for brevity)
    int maxiter = 100; // User input?
    FloatArray stressC, deltaStrain, strain, stress, res;
    stressC.resize( sControl.giveSize() );
    res.resize( sControl.giveSize() );

    FloatMatrix tangent, reducedTangent;
    for ( int istep = 1; istep <= this->numberOfSteps; ++istep ) {
        this->timer.startTimer(EngngModelTimer :: EMTT_SolutionStepTimer);
        for ( int imat = 1; imat <= d->giveNumberOfMaterialModels(); ++imat ) {
            GaussPoint *gp = gps[imat-1].get();
            StructuralMaterial *mat = static_cast< StructuralMaterial * >( d->giveMaterial(imat) );
            StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) );

            strain = status->giveStrainVector();
            // Update the controlled parts
            for ( int j = 1; j <= eControl.giveSize(); ++j ) {
                int p = eControl.at(j);
                strain.at(p) = d->giveFunction( cmpntFunctions.at(p) )->evaluateAtTime( tStep->giveIntrinsicTime() );
            }

            for ( int j = 1; j <= sControl.giveSize(); ++j ) {
                int p = sControl.at(j);
                stressC.at(j) = d->giveFunction( cmpntFunctions.at(p) )->evaluateAtTime( tStep->giveIntrinsicTime() );
            }

            //strain.add(-100, {6.27e-06,  6.27e-06, 6.27e-06, 0, 0, 0});
            for ( int iter = 1; iter < maxiter; iter++ ) {
#if 0
                // Debugging:
                mat->give3dMaterialStiffnessMatrix(tangent, TangentStiffness, gp, tStep);
                tangent.printYourself("# tangent");
                
                strain.zero();
                mat->giveRealStressVector_3d(stress, gp, strain, tStep);
                FloatArray strain2;
                tangent.solveForRhs(stress, strain2);
                strain2.printYourself("# thermal expansion");
                break;
#endif

                strain.printYourself("Macro strain guess");
                mat->giveRealStressVector_3d(stress, gp, strain, tStep);
                for ( int j = 1; j <= sControl.giveSize(); ++j ) {
                    res.at(j) = stressC.at(j) - stress.at( sControl.at(j) );
                }

                OOFEM_LOG_INFO("*** Time step: %d (t = %.2e), Material %d, Iteration: %d,  Residual = %e (tolerance %.2e)\n", 
                              istep, tStep->giveIntrinsicTime(), imat, iter, res.computeNorm(), tolerance);

                if ( res.computeNorm() <= tolerance ) {
                    break;
                } else {
                    if ( tangent.giveNumberOfRows() == 0 || !keepTangent ) {
                        mat->give3dMaterialStiffnessMatrix(tangent, TangentStiffness, gp, tStep);
                    }

                    // Pick out the stress-controlled part;
                    reducedTangent.beSubMatrixOf(tangent, sControl, sControl);

                    // Update stress-controlled part of the strain
                    reducedTangent.solveForRhs(res, deltaStrain);
                    //deltaStrain.printYourself("deltaStrain");
                    for ( int j = 1; j <= sControl.giveSize(); ++j ) {
                        strain.at( sControl.at(j) ) += deltaStrain.at(j);
                    }
                }
            }

            if ( res.computeNorm() > tolerance ) {
                OOFEM_WARNING("Residual did not converge!");
            }

            // This material model has converged, so we update it and go on to the next.
            gp->updateYourself(tStep);
        }

        this->timer.stopTimer(EngngModelTimer :: EMTT_SolutionStepTimer);
        this->doStepOutput(tStep);
        tStep = giveNextStep();
    }

    this->timer.stopTimer(EngngModelTimer :: EMTT_AnalysisTimer);
    this->outfile.close();
}
Exemplo n.º 3
0
FloatArray FloatArray::subArray(int offset, int length){
  ASSERT(size >= offset+length, "Array too small");
  return FloatArray(data+offset, length);
}
Exemplo n.º 4
0
 FloatArray getSamples(int channel) {
     return FloatArray(buffer[channel], size);
 }
Exemplo n.º 5
0
boost::shared_ptr<PrimVars> EmitterMesh::particlesOnFace(int faceIdx)
{
	const MeshFace& face = m_faces[faceIdx];

	boost::shared_ptr<PrimVars> interpVars(new PrimVars());

	float numParticlesCts = face.weight*m_totParticles;
	int numParticles = Aqsis::lfloor(face.weight*m_totParticles);
	if(numParticlesCts - numParticles > uRand())
		++numParticles;
	if(numParticles == 0)
		return boost::shared_ptr<PrimVars>();
	std::vector<int> storageCounts;
	// Create storage for all interpolated output parameters.
	for(PrimVars::const_iterator i = m_primVars->begin(), end = m_primVars->end();
			i != end; ++i)
	{
		if(i->token.Class() == Aqsis::class_constant
				|| i->token.Class() == Aqsis::class_uniform)
		{
			storageCounts.push_back(0);
			// uniform and constant primvars on the mesh interpolate to
			// constant primvars on the curves
			interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_constant,
				i->token.type(), i->token.count(), i->token.name() + "_emit"));
			// We can just copy over constant/uniform data; no interpolation needed.
			if(i->token.Class() == Aqsis::class_constant)
				*interpVars->back().value = *i->value;
			else
			{
				int stride = i->token.storageCount();
				interpVars->back().value->assign(
						i->value->begin() + stride*faceIdx,
						i->value->begin() + stride*(faceIdx+1));
			}
		}
		else
		{
			storageCounts.push_back(i->token.storageCount());
			// varying, vertex, facevarying and facevertex primvars interpolate
			// to uniform primvars on the curves
			interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_uniform,
				i->token.type(), i->token.count(), i->token.name() + "_emit"));
			// Allocate storage
			interpVars->back().value->assign(numParticles*storageCounts.back(), 0);
		}
	}

	// Float offsets for randomized quasi Monte-Carlo distribution
	float uOffset = float(std::rand())/RAND_MAX;
	float vOffset = float(std::rand())/RAND_MAX;
	// loop over child particles
	for(int particleNum = 0; particleNum < numParticles; ++particleNum)
	{
		// get random weights for the vertices of the current face.
		float u = uOffset + m_lowDiscrep.Generate(0, particleNum);
		if(u > 1)
			u -= 1;
		float v = vOffset + m_lowDiscrep.Generate(1, particleNum);
		if(v > 1)
			v -= 1;
		float weights[4];
		if(face.numVerts == 3)
		{
			if(u + v > 1)
			{
				u = 1-u;
				v = 1-v;
			}
			weights[0] = 1 - u - v;
			weights[1] = u;
			weights[2] = v;
			weights[3] = 0.0f;
		}
		else
		{
			weights[0] = (1-u)*(1-v);
			weights[1] = (1-u)*v;
			weights[2] = u*v;
			weights[3] = u*(1-v);
		}

		// loop over primitive variables.  Each varying/vertex/facevarying
		// /facevertex primvar is interpolated from the parent mesh to the
		// current child particle.
		int storageIndex = 0;
		PrimVars::iterator destVar = interpVars->begin();
		for(PrimVars::const_iterator srcVar = m_primVars->begin(),
				end = m_primVars->end(); srcVar != end;
				++srcVar, ++storageIndex, ++destVar)
		{
			int storageStride = storageCounts[storageIndex];
			// Get pointers to source parameters for the vertices
			const float* src[4] = {0,0,0,0};
			switch(srcVar->token.Class())
			{
				case Aqsis::class_varying:
				case Aqsis::class_vertex:
					for(int i = 0; i < face.numVerts; ++i)
						src[i] = &(*srcVar->value)[storageStride*face.v[i]];
					break;
				case Aqsis::class_facevarying:
				case Aqsis::class_facevertex:
					for(int i = 0; i < face.numVerts; ++i)
						src[i] = &(*srcVar->value)[
							storageStride*(face.faceVaryingIndex+i) ];
					break;
				default:
					// Other classes don't need any interpolation, so we just
					// go to the next primvar in m_primVars
					continue;
			}

			// Interpolate the primvar pointed to by srcVar to the current
			// particle position.  This is just a a weighted average of values
			// attached to vertices of the current face.
			float* dest = &(*destVar->value)[storageStride*particleNum];
			for(int k = 0; k < storageStride; ++k, ++dest)
			{
				*dest = 0;
				for(int i = 0; i < face.numVerts; ++i)
				{
					*dest += *src[i] * weights[i];
					++src[i];
				}
			}
		}
	}

	// Finally, add extra face-constant parameters.
	Vec3 Ng_emitVec = faceNormal(face);
	float Ng_emit[] = {Ng_emitVec.x(), Ng_emitVec.y(), Ng_emitVec.z()};
	interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_constant, Aqsis::type_normal,
				1, "Ng_emit"), FloatArray(Ng_emit, Ng_emit+3));

	return interpVars;
}
Exemplo n.º 6
0
IRResultType Delamination :: initializeFrom(InputRecord *ir)
{
    IRResultType result;                   // Required by IR_GIVE_FIELD macro

    result = EnrichmentItem :: initializeFrom(ir);
    if ( result != IRRT_OK ) return result;

    // Compute the delamination xi-coord
    IR_GIVE_FIELD(ir, this->interfaceNum, _IFT_Delamination_interfacenum); // interface number from the bottom
    IR_GIVE_FIELD(ir, this->crossSectionNum, _IFT_Delamination_csnum);
    if ( ir->hasField(_IFT_Delamination_averageStresses) ) {
        this->recoverStresses = false;
        //printf("averageStresses");
    }
    
#if 1
    // update: csnum is now an IntArray of cross sections viable for delamination
    bool checkCS = false; 
    double totalThickness(0.0);
    FloatArray layerThicknesses;
    int numberOfLayers(0);
    for (int iCS : this->crossSectionNum) {
        LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveDomain()->giveCrossSection(iCS) );
        if ( layeredCS == NULL ) {
            OOFEM_WARNING("Delamination EI requires a valid layered cross section number input: see record '%s'.", _IFT_Delamination_csnum);
            return IRRT_BAD_FORMAT;
        } else if ( this->interfaceNum.giveSize() < 1 || this->interfaceNum.giveSize() > 2 ) {
            OOFEM_WARNING("Size of record 'interfacenum' must be 1 or 2");
            return IRRT_BAD_FORMAT;
        }

        // check that interface numbers are valid
        //interfaceNum.printYourself("interface num");
        for ( int i = 1; i <= this->interfaceNum.giveSize(); i++ ) {
            if ( this->interfaceNum.at(i) < 1 || this->interfaceNum.at(i) >= layeredCS->giveNumberOfLayers() ) {
                OOFEM_WARNING( "Cross section does not contain the interface number (%d) specified in the record '%s' since number of layers is %d.", this->interfaceNum.at(i), _IFT_Delamination_interfacenum, layeredCS->giveNumberOfLayers() );
                return IRRT_BAD_FORMAT;
            }
        }
        
        
        if (checkCS) {
            if ( layeredCS->give(CS_Thickness, FloatArray(), NULL, false) != totalThickness ) {
                OOFEM_WARNING("Delamination cross section have different totalThickness: see record '%s'.", _IFT_Delamination_csnum);
                return IRRT_BAD_FORMAT;
            }
            if ( layeredCS->giveNumberOfLayers() != numberOfLayers ) {
                OOFEM_WARNING("Delamination cross section have different number of layers: see record '%s'.", _IFT_Delamination_csnum);
                return IRRT_BAD_FORMAT;
            }
            
        } else 
        numberOfLayers = layeredCS->giveNumberOfLayers();
        totalThickness = layeredCS->give(CS_Thickness, FloatArray(), NULL, false); // no position available
        for ( int i = 1 ; i <= numberOfLayers ; i++) {
            double layerThickness = layeredCS->giveLayerThickness(i);
            if (checkCS) {
                if ( layerThickness != layerThicknesses.at(i) ) {
                    OOFEM_WARNING("Delamination cross section have different layer thicknesses: see record '%s'.", _IFT_Delamination_csnum);
                    return IRRT_BAD_FORMAT;
                }
                layerThicknesses.at(i) = layerThickness;
            } else {
                layerThicknesses.append(layeredCS->giveLayerThickness(i));
            }
        }

        // compute xi-coord of the delamination
        this->delamXiCoord = -1.0;
        this->xiBottom = -1.0;
        for ( int i = 1; i <= this->interfaceNum.at(1); i++ ) {
            this->delamXiCoord += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
            this->xiBottom += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
        }

        if ( this->interfaceNum.giveSize() == 2 ) {
            if ( this->interfaceNum.at(1) >= this->interfaceNum.at(2) ) {
                OOFEM_WARNING("second intercfacenum must be greater than the first one");
                return IRRT_BAD_FORMAT;
            }
            this->xiTop = -1.0;
            for ( int i = 1; i <= this->interfaceNum.at(2); i++ ) {
                this->xiTop += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
            }
        } else {
            this->xiTop = 1.0; // default is the top surface
        }
        checkCS = true;
    }
#else
    // old csnum (int version). NB: this was a bug since element nodes that where not part of the cross section could be enriched. 
    LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveDomain()->giveCrossSection(this->crossSectionNum) );
    if ( layeredCS == NULL ) {
        OOFEM_WARNING("Delamination EI requires a valid layered cross section number input: see record '%s'.", _IFT_Delamination_csnum);
        return IRRT_BAD_FORMAT;
    } else if ( this->interfaceNum.giveSize() < 1 || this->interfaceNum.giveSize() > 2 ) {
        OOFEM_WARNING("Size of record 'interfacenum' must be 1 or 2");
        return IRRT_BAD_FORMAT;
    }

    // check that interface numbers are valid
    //interfaceNum.printYourself("interface num");
    for ( int i = 1; i <= this->interfaceNum.giveSize(); i++ ) {
        if ( this->interfaceNum.at(i) < 1 || this->interfaceNum.at(i) >= layeredCS->giveNumberOfLayers() ) {
            OOFEM_WARNING( "Cross section does not contain the interface number (%d) specified in the record '%s' since number of layers is %d.", this->interfaceNum.at(i), _IFT_Delamination_interfacenum, layeredCS->giveNumberOfLayers() );
            return IRRT_BAD_FORMAT;
        }
    }

    // compute xi-coord of the delamination
    this->delamXiCoord = -1.0;
    double totalThickness = layeredCS->give(CS_Thickness, FloatArray(), NULL, false); // no position available
    for ( int i = 1; i <= this->interfaceNum.at(1); i++ ) {
        this->delamXiCoord += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
        this->xiBottom += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
    }

    if ( this->interfaceNum.giveSize() == 2 ) {
        if ( this->interfaceNum.at(1) >= this->interfaceNum.at(2) ) {
            OOFEM_WARNING("second intercfacenum must be greater than the first one");
            return IRRT_BAD_FORMAT;
        }
        for ( int i = 1; i <= this->interfaceNum.at(2); i++ ) {
            this->xiTop += layeredCS->giveLayerThickness(i) / totalThickness * 2.0;
        }
    } else {
        this->xiTop = 1.0; // default is the top surface
    }
#endif


    IR_GIVE_OPTIONAL_FIELD(ir, this->matNum, _IFT_Delamination_CohesiveZoneMaterial);
    if ( this->matNum > 0 ) {
        this->mat = this->giveDomain()->giveMaterial(this->matNum);
    }
    
    IR_GIVE_OPTIONAL_FIELD(ir, this->initiationFactor, _IFT_Delamination_initiationFactor);
    if ( this->initiationFactor <= 0 ) {
        OOFEM_ERROR("initiation scale factor must be greater than 0.");
        return IRRT_BAD_FORMAT;
    }
    
    IR_GIVE_OPTIONAL_FIELD(ir, this->initiationRadius, _IFT_Delamination_initiationRadius);
    if ( this->initiationRadius < 0 ) {
        OOFEM_ERROR("initiation radius must be greater or equal than 0.");
        return IRRT_BAD_FORMAT;
    }
    

    return IRRT_OK;
}
Exemplo n.º 7
0
Matrix::Matrix(){
    
    FloatArray();
}