1 (edited by Mikael Öhman 06-05-2010 01:24:57)

Topic: Some issues with homogenization, strange boundary conditions and more

Hello again. I have some problems with implementations of "strange" models in OOFEM again.
I'd like to note that I don't disagree with the design of OOFEM, I'm just looking to handle these problems in the best way. It is very possible that I have missed something that will greatly help me with these problems.

I have one of the most typical multiscale problems. Applying and solving the problem at the subscale is not an issue, but when it comes to homogenization, everything seems to become increasingly bothersome.

I typically need to use the stiffness matrix on the micro scale from the last iteration, so I'll denote it "K".

  • First, I need to calculate the homogenized stress. Several ways to do this, the simplest would be to take the nodal forces for the locked degrees of freedom, then multiply by their coordinates and sum it up. I'm not sure how to obtain the reaction forces.

  • Secondly, I need the macroscopic stiffness matrix. For this I also require the whole stiffness matrix, and split it up into free and prescribed parts. Then I solve the solution for 3 (in 2D) different boundary conditions using parts of the tangent matrix K. (Since we are in the tangent space, the problem is linear, i.e. different from whatever problem is actually solved at the microscale).

The best idea I got so far, is to deactivate the boundary condition and generate the whole matrix again, then mess around a whole lot with equation numbers, trying to split the matrix. Is this the way to go?

A short, I need to calculate something like this (in pseudo-matlab syntax)
K*a = f
Splitting it up as;
[K_bb, K_bi; K_ib, K_ii].[a_b; a_i] = [r_b;0]
where a_b is prescribed values (As I've mentioned in another post, this is the dirichlet B.C i implemented for the subscale)
a_b = C*d  (where d is a macroscopic tensor, d = [d_11; d_22; d_12], and C is some matrix)
E = C'*(K_bb - K_bi*K_ii\K_ib)*C
where E is the macroscopic stiffness.
r_b are the reaction forces that I need to calculate the macroscopic stress.

I have also encountered some problems with some boundary conditions. For example, I would like to constrict the velocities in some constrained nodes to fullfill
v_i = d_ij*x_j
where d_11, d_12 (=d_21), d_22 are unknowns as well (macroscopic rate of deformation gradient).
It's quite simple to split the complete system of equations, and add corresponding equations for the new unknowns. The load for these new equations would also be the macroscopic stress tensor.
Other cases could range from unknown loads to unknown velocities.
These issues are not as important.

Re: Some issues with homogenization, strange boundary conditions and more

I just found EModelDefaultPrescribedEquationNumbering() which I hadn't seen before. Perfect! There are just some issues;
1. Construction of the element stiffness has to be repeated.
2. I could only get the K_bb and K_ii parts, as K_bi and K_ib requires a mix.
So, I will need to add another assembling routine for mixed UnknownNumberingScheme's.
The sparse matrices already support mixed assembling, so it's just one function to the engineering model.
I see that there is another assemble routine for mixed equation id. But i can't say I understand it's use.

Also, some small change needs to be done for the routines "buildInternalStructure" as it enforces square matrices.

3

Re: Some issues with homogenization, strange boundary conditions and more

Hi Mikael,

as you have explored, using several equation numbering schemes could solve the problem. Please note, that reaction forces in OOFEM are not computed using Kbb, but by assembling nodal forces for prescribed DOFS - so the assembly of kbb is not necessary and works for nonlinear problems as well! )

Perhaps you may also think about using custom numbering which assigns equation number to all dofs (unknown as well as prescribed) and use idea of Irons and Payne to impose boundary conditions indirectly by modifying stiffness matrix and load vector.
This is achieved by adding a large number alpha to the  diagonal member of K corresponding to prescribed DOF  and replacing the right-hand side by alpha*prescribed_value. If alpha is very much larger than other stiffness coefficients then this alteration effectively replaces the corresponding equation by  alpha*unknown_value = alpha*prescribed_value.

Borek

Re: Some issues with homogenization, strange boundary conditions and more

Hi Borek.

The Kbb part is necessary to calculate the macroscopic tangent, even if it's not needed to solve the microscopic problem itself.
I realized also, that even if i had the whole matrix, splitting up the sparse matrices seemed like a very bad idea.

I can't see any reasonable way to compute this
C'*(K_bb - K_bi*K_ii\K_ib)*C
without obtaining these matrices induvidually. (C is a matrix i can construct knowing the prescribed dofs).

I didn't have to create any custom numbering, In fact, OOFEM already supports what i want to achieve, except for a few things;

* Building the internal structure for sparse matrices, it assumes to much about the size.
I implemented another version which respect the numberingscheme even for prescribed values, i.e;
buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)

* EngngModel->assemble didn't support mixed numberingschemes. Adding this was trivial.

* Petsc sparse matrices didn't support times(FloatArray &x,FloatArray &y);. But this was quite easy, so i implemented it already. I also added timesT (transpose) since I needed it as well, but I see no harm in that.

All other routines already natively supported

This seems to fit well into the design of OOFEM, and I don't think anything I've implemented would count as a hack, so I'm quite pleased with the results.

Since I need to do a bit of matrix operations (especially on sparse structures) I'm planning on filling up the gaps in the current implementations. Also for dense matrices, FloatMatrix and FloatArray. I'd like to have some basic BLAS operations.

5

Re: Some issues with homogenization, strange boundary conditions and more

Hi Mikael,

I can't see any reasonable way to compute this
C'*(K_bb - K_bi*K_ii\K_ib)*C
without obtaining these matrices induvidually. (C is a matrix i can construct knowing the prescribed dofs).

I fully agree.

* Building the internal structure for sparse matrices, it assumes to much about the size.
I implemented another version which respect the numberingscheme even for prescribed values, i.e;
buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)

Does it men that you need to number unknown DOFs as well as prescribed DOFs? This could be achieved using existing routine and using custom numbering scheme. From my point of view, when thinking about coupled multi-physic simulations, it would be nice to pass rather several EquationIDs, so that the internal structure is built for several equations (mass balance, momentum balance, etc).

EngngModel->assemble didn't support mixed numberingschemes. Adding this was trivial.

Again, I think that you can use existing routine, but with custom numbering scheme. That why these schemes were introduced.

Since I need to do a bit of matrix operations (especially on sparse structures) I'm planning on filling up the gaps in the current implementations. Also for dense matrices, FloatMatrix and FloatArray. I'd like to have some basic BLAS operations.

I will be definitely interested in this.

Borek

Re: Some issues with homogenization, strange boundary conditions and more

bp wrote:

Hi Mikael,

* Building the internal structure for sparse matrices, it assumes to much about the size.
I implemented another version which respect the numberingscheme even for prescribed values, i.e;
buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)

Does it men that you need to number unknown DOFs as well as prescribed DOFs? This could be achieved using existing routine and using custom numbering scheme. From my point of view, when thinking about coupled multi-physic simulations, it would be nice to pass rather several EquationIDs, so that the internal structure is built for several equations (mass balance, momentum balance, etc).

EngngModel->assemble didn't support mixed numberingschemes. Adding this was trivial.

Again, I think that you can use existing routine, but with custom numbering scheme. That why these schemes were introduced.

The current code in buildInternalStructure assumes that the matrix is always square, and the size is the number of free equations, regardless of what numberingsscheme is submitted, so something definitely needs to be changed.

I dont think I could mix things up with another numbering scheme.
When it comes down to it, regardless of numbering scheme, EngngModel::assemble is just calling

        if ( mat.isNotEmpty() ) {
            if ( answer->assemble(loc, mat) == 0 ) {
                _error("assemble: sparse matrix assemble error");
            }
        }

with a single IntArray which is used for both columns and rows.

I'm suggesting that one adds the function

void EngngModel :: assemble(SparseMtrx *answer, TimeStep *tStep, EquationID ut,
                            CharType type, const UnknownNumberingScheme &rs, const UnknownNumberingScheme &cs,
                            Domain *domain)
// Same as assemble, but with different numbering for rows and columns
{
    int ielem;
    IntArray r_loc, c_loc;
    FloatMatrix mat;
    Element *element;

    if ( answer == NULL ) {
        _error("assemble: NULL pointer encountered.");
    }

    this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
    int nelem = domain->giveNumberOfElements();
    for ( ielem = 1; ielem <= nelem; ielem++ ) {
        element = domain->giveElement(ielem);
#ifdef __PARALLEL_MODE
        // skip remote elements (these are used as mirrors of remote elements on other domains
        // when nonlocal constitutive models are used. They introduction is necessary to
        // allow local averaging on domains without fine grain communication between domains).
        if ( element->giveParallelMode() == Element_remote ) {
            continue;
        }

#endif

        this->giveElementCharacteristicMatrix(mat, ielem, type, tStep, domain);
        if ( mat.isNotEmpty() ) {
///////////////// I added this part, mixed numbering   ///////////////////////////
            element->giveLocationArray(r_loc, ut, rs);
            element->giveLocationArray(c_loc, ut, cs);
            if ( answer->assemble(r_loc, c_loc, mat) == 0 ) {
                _error("assemble: sparse matrix assemble error");
            }
        }
    }

    this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);

    answer->assembleBegin();
    answer->assembleEnd();
}

which is very similar the the routine for mixed EquationID, but for numberingschemes instead. I dont see how you could create a mixed matrix like this without adding this assemble routine.

I did this, and now I can assemble the mixed matrices by doing

    this->assemble( this->K_cf, tStep, EID_MomentumBalance_ConservationEquation,
            StiffnessMatrix, EModelDefaultPrescribedEquationNumbering(),
            EModelDefaultEquationNumbering(), this->giveDomain(1));

Since I need to do a bit of matrix operations (especially on sparse structures) I'm planning on filling up the gaps in the current implementations. Also for dense matrices, FloatMatrix and FloatArray. I'd like to have some basic BLAS operations.

I will be definitely interested in this.

Borek

Nice to hear. I have also been filling in some gaps in the FEI classes. I will be starting to send you some patches by next week.

7

Re: Some issues with homogenization, strange boundary conditions and more

Hi Mikael,
just short note, regarding the assembly. Have you noticed the following routine:

void EngngModel :: assemble(SparseMtrx *answer, TimeStep *tStep, EquationID r_id, EquationID c_id,
                            CharType type, const UnknownNumberingScheme &ns,
                            Domain *domain)

It allows to assemble contributions with different row and column location numbers (identified by EquationIDs).

Borek

Re: Some issues with homogenization, strange boundary conditions and more

Yes I've seen that function as well.
I want to keep the same equation ID for both of them (EID_MomentumBalanceConservationEquation to be exact), but different numbering schemes for rows and columns instead.

It was thanks to this function that I didn't have to write anything for the sparse matrices themselves, as they already support mixed IntArrays for columns and rows (regardless whether or not these are obtained by mixing EquationID or UnKnownNumberingScheme).