Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1998-11-17
// Created by: Igor FEOKTISTOV
// Copyright (c) 1998-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <FEmTool_Assembly.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_List.hxx>
#include <FEmTool_ProfileMatrix.hxx>
#include <math_Matrix.hxx>
#include <Standard_DomainError.hxx>
#include <StdFail_NotDone.hxx>
//=================================================================================================
static int MinIndex(
const occ::handle<NCollection_HArray2<occ::handle<NCollection_HArray1<int>>>>& Table)
{
int dim, el, nvar, Imin;
int diml = Table->LowerRow(), dimu = Table->UpperRow(), ell = Table->LowerCol(),
elu = Table->UpperCol(), nvarl, nvaru;
occ::handle<NCollection_HArray1<int>> T = Table->Value(diml, ell);
nvarl = T->Lower();
Imin = T->Value(nvarl);
for (dim = diml; dim <= dimu; dim++)
{
for (el = ell; el <= elu; el++)
{
T = Table->Value(dim, el);
nvarl = T->Lower();
nvaru = T->Upper();
for (nvar = nvarl; nvar <= nvaru; nvar++)
{
Imin = std::min(Imin, T->Value(nvar));
}
}
}
return Imin;
}
//=================================================================================================
static int MaxIndex(
const occ::handle<NCollection_HArray2<occ::handle<NCollection_HArray1<int>>>>& Table)
{
int dim, el, nvar, Imax;
int diml = Table->LowerRow(), dimu = Table->UpperRow(), ell = Table->LowerCol(),
elu = Table->UpperCol(), nvarl, nvaru;
occ::handle<NCollection_HArray1<int>> T = Table->Value(diml, ell);
nvarl = T->Lower();
Imax = T->Value(nvarl);
for (dim = diml; dim <= dimu; dim++)
{
for (el = ell; el <= elu; el++)
{
T = Table->Value(dim, el);
nvarl = T->Lower();
nvaru = T->Upper();
for (nvar = nvarl; nvar <= nvaru; nvar++)
{
Imax = std::max(Imax, T->Value(nvar));
}
}
}
return Imax;
}
//=================================================================================================
FEmTool_Assembly::FEmTool_Assembly(
const NCollection_Array2<int>& Dependence,
const occ::handle<NCollection_HArray2<occ::handle<NCollection_HArray1<int>>>>& Table)
: myDepTable(1, Dependence.ColLength(), 1, Dependence.RowLength()),
B(MinIndex(Table), MaxIndex(Table))
{
IsSolved = false;
myDepTable = Dependence;
myRefTable = Table;
NCollection_Array1<int> FirstIndexes(1, B.Length());
FirstIndexes.Init(B.Length());
int dim, el, nvar, Imin, I0 = 1 - B.Lower(), i;
int diml = Table->LowerRow(), dimu = Table->UpperRow(), ell = Table->LowerCol(),
elu = Table->UpperCol(), nvarl, nvaru;
occ::handle<NCollection_HArray1<int>> T;
for (dim = diml; dim <= dimu; dim++)
{
for (el = ell; el <= elu; el++)
{
T = Table->Value(dim, el);
nvarl = T->Lower();
nvaru = T->Upper();
Imin = T->Value(nvarl) + I0;
for (nvar = nvarl; nvar <= nvaru; nvar++)
{
Imin = std::min(Imin, T->Value(nvar) + I0);
}
for (nvar = nvarl; nvar <= nvaru; nvar++)
{
i = T->Value(nvar) + I0;
FirstIndexes(i) = std::min(FirstIndexes(i), Imin);
}
}
}
H = new FEmTool_ProfileMatrix(FirstIndexes);
NullifyMatrix();
NullifyVector();
}
void FEmTool_Assembly::NullifyMatrix()
{
H->Init(0.);
IsSolved = false;
}
//=================================================================================================
void FEmTool_Assembly::AddMatrix(const int Element,
const int Dimension1,
const int Dimension2,
const math_Matrix& Mat)
{
if (myDepTable(Dimension1, Dimension2) == 0)
{
throw Standard_DomainError("FEmTool_Assembly::AddMatrix");
}
const NCollection_Array1<int>& T1 = myRefTable->Value(Dimension1, Element)->Array1();
const NCollection_Array1<int>& T2 = myRefTable->Value(Dimension2, Element)->Array1();
int nvarl = T1.Lower(), nvaru = std::min(T1.Upper(), nvarl + Mat.RowNumber() - 1);
int I, J, I0 = 1 - B.Lower(), i, ii, j,
i0 = Mat.LowerRow() - nvarl, j0 = Mat.LowerCol() - nvarl;
for (i = nvarl; i <= nvaru; i++)
{
I = T1(i) + I0;
ii = i0 + i;
for (j = nvarl; j <= i; j++)
{
J = T2(j) + I0;
H->ChangeValue(I, J) += Mat(ii, j0 + j);
}
}
IsSolved = false;
}
//=================================================================================================
void FEmTool_Assembly::NullifyVector()
{
B.Init(0.);
}
//=================================================================================================
void FEmTool_Assembly::AddVector(const int Element, const int Dimension, const math_Vector& Vec)
{
const NCollection_Array1<int>& T = myRefTable->Value(Dimension, Element)->Array1();
int nvarl = T.Lower(), nvaru = std::min(T.Upper(), nvarl + Vec.Length() - 1),
i0 = Vec.Lower() - nvarl;
// int I, i;
int i;
for (i = nvarl; i <= nvaru; i++)
{
B(T(i)) += Vec(i0 + i);
}
}
//=================================================================================================
bool FEmTool_Assembly::Solve()
{
IsSolved = H->Decompose();
#ifdef OCCT_DEBUG
if (!IsSolved)
{
std::cout << "Solve Echec H = " << std::endl;
H->OutM();
}
#endif
/* ????
while(!IsSolved && count < 5) {
int i;
for(i = 1; i <= H->RowNumber(); i++) {
H->ChangeValue(i,i) *= 2.;
}
IsSolved = H->Decompose();
count++;
}
*/
// int count = 0;
if (!G.IsEmpty() && IsSolved)
{
// calculating H-1 Gt
math_Vector gi(B.Lower(), B.Upper()), qi(B.Lower(), B.Upper());
if (GHGt.IsNull() || GHGt->RowNumber() != G.Length())
{
NCollection_Array1<int> FirstIndexes(1, G.Length());
//-----------------------------------------------------------------
NCollection_Array2<int> H1(1, NbGlobVar(), 1, NbGlobVar());
H1.Init(1);
int i, j, k, l, BlockBeg = 1, BlockEnd;
bool Block, Zero;
for (i = 2; i <= NbGlobVar(); i++)
{
BlockEnd = i - 1;
if (!H->IsInProfile(i, BlockEnd))
{
// Maybe, begin of block
Block = true;
for (j = i + 1; j <= NbGlobVar(); j++)
{
if (H->IsInProfile(j, BlockEnd))
{
Block = false;
break;
}
}
if (Block)
{
for (j = i; j <= NbGlobVar(); j++)
{
for (k = BlockBeg; k <= BlockEnd; k++)
{
H1(j, k) = 0;
H1(k, j) = 0;
}
}
BlockBeg = BlockEnd + 1;
}
else
{
i = j;
}
}
}
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter1;
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter2;
for (i = 1; i <= G.Length(); i++)
{
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& Gi = G.Value(i);
for (j = 1; j <= i; j++)
{
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& Gj = G.Value(j);
Zero = true;
for (Iter1.Initialize(Gi); Iter1.More(); Iter1.Next())
{
const occ::handle<NCollection_HArray1<double>>& a = Iter1.Value();
for (k = a->Lower(); k <= a->Upper(); k++)
{
for (Iter2.Initialize(Gj); Iter2.More(); Iter2.Next())
{
const occ::handle<NCollection_HArray1<double>>& b = Iter2.Value();
for (l = b->Lower(); l <= b->Upper(); l++)
{
if (H1(k, l) != 0)
{
Zero = false;
break;
}
}
if (!Zero)
{
break;
}
}
if (!Zero)
{
break;
}
}
if (!Zero)
{
break;
}
}
if (!Zero)
{
FirstIndexes(i) = j;
break;
}
}
}
//-----------------------------------------------------------------------
// for(i = FirstIndexes.Lower(); i <= FirstIndexes.Upper(); i++)
// std::cout << "FirstIndexes(" << i << ") = " << FirstIndexes(i) << std::endl;
// FirstIndexes.Init(1); // temporary GHGt is full matrix
GHGt = new FEmTool_ProfileMatrix(FirstIndexes);
}
GHGt->Init(0.);
int i, j, k;
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter;
for (i = 1; i <= G.Length(); i++)
{
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& L = G.Value(i);
gi.Init(0.);
// preparing i-th line of G (or column of Gt)
for (Iter.Initialize(L); Iter.More(); Iter.Next())
{
const occ::handle<NCollection_HArray1<double>>& a = Iter.Value();
for (j = a->Lower(); j <= a->Upper(); j++)
{
gi(j) = a->Value(j); // gi - full line of G
}
}
// -1 t
H->Solve(gi, qi); // solving H*qi = gi, qi is column of H G
// -1 t
// Calculation of product M = G H G
// for each i all elements of i-th column of M are calculated for k >= i
for (k = i; k <= G.Length(); k++)
{
if (GHGt->IsInProfile(k, i))
{
double m = 0.; // m = M(k,i)
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& aL = G.Value(k);
for (Iter.Initialize(aL); Iter.More(); Iter.Next())
{
const occ::handle<NCollection_HArray1<double>>& a = Iter.Value();
for (j = a->Lower(); j <= a->Upper(); j++)
{
m += qi(j) * a->Value(j); // scalar product of
}
// k-th line of G and i-th column of H-1 Gt
}
GHGt->ChangeValue(k, i) = m;
}
}
}
IsSolved = GHGt->Decompose();
/* count = 0;
while(!IsSolved && count < 5) {
for(i = 1; i <= GHGt->RowNumber(); i++) {
GHGt->ChangeValue(i,i) *= 2.;
}
IsSolved = GHGt->Decompose();
count++;
}*/
}
return IsSolved;
}
//=================================================================================================
void FEmTool_Assembly::Solution(math_Vector& Solution) const
{
if (!IsSolved)
{
throw StdFail_NotDone("FEmTool_Assembly::Solution");
}
if (G.IsEmpty())
{
H->Solve(B, Solution);
}
else
{
math_Vector v1(B.Lower(), B.Upper());
H->Solve(B, v1);
math_Vector l(1, G.Length()), v2(1, G.Length());
int i, j;
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter;
for (i = 1; i <= G.Length(); i++)
{
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& L = G.Value(i);
double m = 0.;
for (Iter.Initialize(L); Iter.More(); Iter.Next())
{
const occ::handle<NCollection_HArray1<double>>& a = Iter.Value();
for (j = a->Lower(); j <= a->Upper(); j++)
{
m += v1(j) * a->Value(j); // scalar product
}
// G v1
}
v2(i) = m - C.Value(i);
}
GHGt->Solve(v2, l); // Solving M*l = v2
v1 = B;
// Calculation v1 = B-Gt*l
// v1(j) = B(j) - Gt(j,i)*l(i) = B(j) - G(i,j)*l(i)
//
for (i = 1; i <= G.Length(); i++)
{
const NCollection_List<occ::handle<NCollection_HArray1<double>>>& L = G.Value(i);
for (Iter.Initialize(L); Iter.More(); Iter.Next())
{
const occ::handle<NCollection_HArray1<double>>& a = Iter.Value();
for (j = a->Lower(); j <= a->Upper(); j++)
{
v1(j) -= l(i) * a->Value(j);
}
}
}
H->Solve(v1, Solution);
}
}
int FEmTool_Assembly::NbGlobVar() const
{
return B.Length();
}
void FEmTool_Assembly::GetAssemblyTable(
occ::handle<NCollection_HArray2<occ::handle<NCollection_HArray1<int>>>>& AssTable) const
{
AssTable = AssemblyTable();
}
void FEmTool_Assembly::ResetConstraint()
{
G.Clear();
C.Clear();
}
void FEmTool_Assembly::NullifyConstraint()
{
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter;
int i;
for (i = 1; i <= G.Length(); i++)
{
C.SetValue(i, 0.);
for (Iter.Initialize(G.Value(i)); Iter.More(); Iter.Next())
{
Iter.Value()->Init(0.);
}
}
}
//=================================================================================================
void FEmTool_Assembly::AddConstraint(const int IndexofConstraint,
const int Element,
const int Dimension,
const math_Vector& LinearForm,
const double Value)
{
while (G.Length() < IndexofConstraint)
{
// Add new lines in G
NCollection_List<occ::handle<NCollection_HArray1<double>>> L;
G.Append(L);
C.Append(0.);
}
NCollection_List<occ::handle<NCollection_HArray1<double>>>& L = G.ChangeValue(IndexofConstraint);
occ::handle<NCollection_HArray1<int>> Indexes = myRefTable->Value(Dimension, Element);
int i, Imax = 0, Imin = NbGlobVar();
for (i = Indexes->Lower(); i <= Indexes->Upper(); i++)
{
Imin = std::min(Imin, Indexes->Value(i));
Imax = std::max(Imax, Indexes->Value(i));
}
occ::handle<NCollection_HArray1<double>> Coeff;
if (L.IsEmpty())
{
Coeff = new NCollection_HArray1<double>(Imin, Imax);
Coeff->Init(0.);
L.Append(Coeff);
}
else
{
NCollection_List<occ::handle<NCollection_HArray1<double>>>::Iterator Iter(L);
double s1 = 0, s2 = 0;
occ::handle<NCollection_HArray1<double>> Aux1, Aux2;
for (i = 1; Iter.More(); Iter.Next(), i++)
{
if (Imin >= Iter.Value()->Lower())
{
s1 = i;
Aux1 = Iter.Value();
if (Imax <= Iter.Value()->Upper())
{
s2 = s1;
Coeff = Iter.Value();
break;
}
}
if (Imax <= Iter.Value()->Upper())
{
s2 = i;
Aux2 = Iter.Value();
}
}
if (s1 != s2)
{
if (s1 == 0)
{
if (Imax < Aux2->Lower())
{
// inserting before first segment
Coeff = new NCollection_HArray1<double>(Imin, Imax);
Coeff->Init(0.);
L.Prepend(Coeff);
}
else
{
// merge new and first segment
Coeff = new NCollection_HArray1<double>(Imin, Aux2->Upper());
for (i = Imin; i <= Aux2->Lower() - 1; i++)
{
Coeff->SetValue(i, 0.);
}
for (i = Aux2->Lower(); i <= Aux2->Upper(); i++)
{
Coeff->SetValue(i, Aux2->Value(i));
}
L.First() = Coeff;
}
}
else if (s2 == 0)
{
if (Imin > Aux1->Upper())
{
// append new
Coeff = new NCollection_HArray1<double>(Imin, Imax);
Coeff->Init(0.);
L.Append(Coeff);
}
else
{
// merge new and last segment
Coeff = new NCollection_HArray1<double>(Aux1->Lower(), Imax);
for (i = Aux1->Lower(); i <= Aux1->Upper(); i++)
{
Coeff->SetValue(i, Aux1->Value(i));
}
for (i = Aux1->Upper() + 1; i <= Imax; i++)
{
Coeff->SetValue(i, 0.);
}
L.Last() = Coeff;
}
}
else if (Imin <= Aux1->Upper() && Imax < Aux2->Lower())
{
// merge s1 and new
Coeff = new NCollection_HArray1<double>(Aux1->Lower(), Imax);
for (i = Aux1->Lower(); i <= Aux1->Upper(); i++)
{
Coeff->SetValue(i, Aux1->Value(i));
}
for (i = Aux1->Upper() + 1; i <= Imax; i++)
{
Coeff->SetValue(i, 0.);
}
Iter.Initialize(L);
for (i = 1; i < s1; Iter.Next(), i++)
{
;
}
Iter.ChangeValue() = Coeff;
}
else if (Imin > Aux1->Upper() && Imax >= Aux2->Lower())
{
// merge new and first segment
Coeff = new NCollection_HArray1<double>(Imin, Aux2->Upper());
for (i = Imin; i <= Aux2->Lower() - 1; i++)
{
Coeff->SetValue(i, 0.);
}
for (i = Aux2->Lower(); i <= Aux2->Upper(); i++)
{
Coeff->SetValue(i, Aux2->Value(i));
}
Iter.Initialize(L);
for (i = 1; i < s2; Iter.Next(), i++)
{
;
}
Iter.ChangeValue() = Coeff;
}
else if (Imin > Aux1->Upper() && Imax < Aux2->Lower())
{
// inserting new between s1 and s2
Coeff = new NCollection_HArray1<double>(Imin, Imax);
Coeff->Init(0.);
Iter.Initialize(L);
for (i = 1; i < s1; Iter.Next(), i++)
{
;
}
L.InsertAfter(Coeff, Iter);
}
else
{
// merge s1, new, s2 and remove s2
Coeff = new NCollection_HArray1<double>(Aux1->Lower(), Aux2->Upper());
for (i = Aux1->Lower(); i <= Aux1->Upper(); i++)
{
Coeff->SetValue(i, Aux1->Value(i));
}
for (i = Aux1->Upper() + 1; i <= Aux2->Lower() - 1; i++)
{
Coeff->SetValue(i, 0.);
}
for (i = Aux2->Lower(); i <= Aux2->Upper(); i++)
{
Coeff->SetValue(i, Aux2->Value(i));
}
Iter.Initialize(L);
for (i = 1; i < s1; Iter.Next(), i++)
{
;
}
Iter.ChangeValue() = Coeff;
Iter.Next();
L.Remove(Iter);
}
}
}
// adding
int j = LinearForm.Lower();
for (i = Indexes->Lower(); i <= Indexes->Upper(); i++, j++)
{
Coeff->ChangeValue(Indexes->Value(i)) += LinearForm(j);
}
C.ChangeValue(IndexofConstraint) += Value;
}