Page MenuHomec4science

bridging_atomic_continuum.cc
No OneTemporary

File Metadata

Created
Thu, Jul 4, 01:02

bridging_atomic_continuum.cc

/**
* @file bridging_atomic_continuum.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Mon Oct 28 19:23:14 2013
*
* @brief Bridging object between atomistic and finite elements
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
//#define TIMER
/* -------------------------------------------------------------------------- */
#include "bridging_atomic_continuum.hh"
#include "compute_extract.hh"
#include "lib_bridging.hh"
#include "lm_common.hh"
#include "reference_manager.hh"
#include "trace_atom.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
template <typename DomainA, typename DomainC, UInt Dim>
BridgingAtomicContinuum<DomainA, DomainC, Dim>::BridgingAtomicContinuum(
const std::string &name, DomainA &A, DomainC &C)
: LMObject(name), Bridging<typename DomainA::ContainerAtoms,
typename DomainC::ContainerPoints, Dim>(
name, A.getContainer(), C.getContainer()),
domA(A), domC(C), comm_group_continuum(domC.getCommGroup()),
comm_group_atomic(domA.getCommGroup()) {
if (domA.getContainer().hasRefManager())
domA.getContainer().getRefManager()->addSubSet("atomes_rec_subset",
this->pointList);
field_sizes[0] = Dim;
field_sizes[1] = Dim;
field_sizes[2] = Dim;
field_sizes[3] = 1;
is_in_continuum = comm_group_continuum.amIinGroup();
is_in_atomic = comm_group_atomic.amIinGroup();
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
BridgingAtomicContinuum<DomainA, DomainC, Dim>::~BridgingAtomicContinuum() {}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::clearAll() {
Parent::clearAll();
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::updateForMigration() {
Parent::updateForMigration();
if (this->check_coherency) {
checkPositionCoherency();
}
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::init() {
Parent::init();
DUMP(this->getID() << " : attach duo vector", DBG_MESSAGE);
if (this->in_group_A) {
try {
this->contA.getRefManager()->attachObject(this->getDuoVector(),
this->pointList);
DUMP(this->getID() << " : attaching Parent::duo_vector", DBG_INFO);
} catch (LibMultiScaleException &e) {
}
}
MPI_Barrier(MPI_COMM_WORLD);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::projectAtomicDOFsOnMesh(
FieldType field) {
if (is_in_continuum && !this->total_points)
DUMP("Warning : atomic container is empty: "
<< "cannot proceed atomic projection (check geometries ?!) "
<< this->getID(),
DBG_WARNING);
if (!Parent::local_points)
return;
Parent::allocateBuffer(Parent::local_points, Dim);
if (is_in_continuum)
this->interpolateAtomicDOFs(field);
this->distributeVectorB2A("correction_fictifs", Parent::buffer, Dim);
if (is_in_atomic)
setAtomicDOFs(field);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::projectAtomicDOFsOnMesh(
FieldType field, ContainerArray<Real> &buffer) {
if (is_in_continuum && !this->total_points)
DUMP("Warning : atomic container is empty: "
<< "cannot proceed atomic projection (check geometries ?!)",
DBG_WARNING);
if (is_in_continuum)
this->interpolateAtomicDOFs(field, buffer);
this->distributeVectorB2A("correction_fictifs", buffer, Dim);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::interpolateAtomicDOFs(
FieldType field_code) {
interpolateAtomicDOFs(field_code, Parent::buffer);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::interpolateAtomicDOFs(
FieldType field_code, ContainerArray<Real> &buffer) {
if (Parent::local_points == 0) {
DUMP("Warning : atomic container is empty: "
<< "cannot proceed atomic projection (check geometries ?!)",
DBG_WARNING);
return;
}
_Vec_ field;
if (field_code == _displacement)
field = domC.getU();
else if (field_code == _velocity)
field = domC.getV();
else
LM_FATAL("field not handled yet " << field_code);
for (UInt i = 0; i < Parent::local_points; ++i) {
LM_ASSERT(i * Dim < buffer.size(), "overflow detected");
buffer[i * Dim] =
this->getShapeMatrix().interpolate(i, field, Parent::assoc[i], 0);
if (Dim > 1)
buffer[i * Dim + 1] =
this->getShapeMatrix().interpolate(i, field, Parent::assoc[i], 1);
if (Dim == 3)
buffer[i * Dim + 2] =
this->getShapeMatrix().interpolate(i, field, Parent::assoc[i], 2);
}
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::setAtomicDOFs(
FieldType field_code) {
if (Parent::local_points == 0) {
DUMP("Warning : atomic container is empty: "
<< "cannot proceed atomic projection (check geometries ?!)",
DBG_WARNING);
return;
}
if (Parent::buffer.size() == 0) {
LM_FATAL("function InterpolateAtomicDOFs should be called first! exiting");
}
UInt at_index = 0;
for (auto &&at : this->pointList) {
at.force() = Vector<Dim>::Zero();
if (field_code == _velocity)
at.velocity() = VectorView<Dim>(&Parent::buffer[at_index * Dim]);
if (field_code == _displacement) {
at.position() =
at.position0() + VectorView<Dim>(&Parent::buffer[at_index * Dim]);
// if (at.position(0) >= xmax) at.position(0) -= xsize;
// else if (at.position(0) < xmin) at.position(0) += xsize;
//****************************************************************
// Guillaume needs to include PBC treatment
//****************************************************************
at.velocity() = Vector<Dim>::Zero();
}
++at_index;
}
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::averageDOFsOnElements(
ContainerArray<Real> &data_mesh, FieldType field) {
LM_FATAL("to adapt");
if (comm_group_atomic == comm_group_continuum) {
ComputeExtract extracted_field("ComputeExtract:" + this->getID());
extracted_field.setParam("FIELD", field);
extracted_field.build(*this->pointList);
Parent::averageOnElements(extracted_field.getArray(), data_mesh, Dim);
return;
}
ComputeExtract extracted_field("ComputeExtract:" + this->getID());
extracted_field.setParam("FIELD", field);
if (is_in_atomic)
extracted_field.build(*this->pointList);
LM_TOIMPLEMENT;
// extracted_field.resize(Parent::local_points * Dim);
/* do communication */
this->communicateBufferAtom2Continuum(Dim, extracted_field.getArray());
if (is_in_continuum)
Parent::averageOnElements(extracted_field.getArray(), data_mesh, Dim);
}
/* -------------------------------------------------------------------------- */
// template <typename DomainA, typename DomainC,UInt Dim>
// template <FieldType field>
// void BridgingAtomicContinuum<DomainA,DomainC,Dim>::
// buildAtomicDOFsVector(std::vector<Real> & v_out){
// IteratorAtomsSubset it = this->pointList->begin();
// UInt nmax = this->pointList->size();
// UInt i =0;
// Real * v_out_ptr = &v_out[0];
// for (RefAtom at = it.getFirst(); !it.end() ;
// at = it.getNext() , ++i, v_out_ptr+= Dim) {
// LM_ASSERT(i < nmax,"overflow detected");
// at.template getField<field>(v_out_ptr);
// }
// }
// /* --------------------------------------------------------------------------
// */
// template <typename DomainA, typename DomainC,UInt Dim>
// void BridgingAtomicContinuum<DomainA,DomainC,Dim>::
// buildAtomicDOFsVector(std::vector<Real> & v_out,
// FieldType field){
// switch(field){
// case _position0: buildAtomicDOFsVector<_position0 >(v_out); break;
// case _position: buildAtomicDOFsVector<_position >(v_out); break;
// case _displacement: buildAtomicDOFsVector<_displacement>(v_out); break;
// case _velocity: buildAtomicDOFsVector<_velocity >(v_out); break;
// case _force: buildAtomicDOFsVector<_force >(v_out);
// break;
// default: LM_FATAL("not handled field");
// }
// }
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::leastSquareAtomicData(
ContainerArray<Real> &data_mesh, ContainerArray<Real> &data_atom,
UInt stride) {
if (comm_group_atomic == comm_group_continuum) {
Parent::solveLeastSquare(data_mesh, data_atom, stride);
return;
}
/* do communication */
this->communicateBufferAtom2Continuum(stride, data_atom);
if (is_in_continuum) {
Parent::solveLeastSquare(data_mesh, data_atom, stride);
}
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::leastSquareAtomicDOFs(
ContainerArray<Real> &data_mesh, FieldType field) {
LM_FATAL("to adapt");
if (comm_group_atomic == comm_group_continuum) {
ComputeExtract extracted_field("ComputeExtract:" + this->getID());
extracted_field.setParam("FIELD", field);
extracted_field.build<ContainerAtomsSubset>(this->pointList);
Parent::solveLeastSquare(data_mesh, extracted_field.getArray(), Dim);
return;
}
ComputeExtract extracted_field("ComputeExtract:" + this->getID());
extracted_field.setParam("FIELD", field);
if (is_in_atomic)
extracted_field.build<ContainerAtomsSubset>(this->pointList);
LM_TOIMPLEMENT;
// extracted_field.resize(Parent::local_points * Dim);
this->leastSquareAtomicData(data_mesh, extracted_field.getArray(), Dim);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::buildAtomicDOFsNoiseVector(
std::vector<Real> &v_out, FieldType field) {
ComputeExtract extracted_field("ComputeExtract:" + this->getID());
extracted_field.setParam("FIELD", field);
if (is_in_atomic)
extracted_field.build(*this->pointList);
if (is_in_continuum) {
this->interpolateAtomicDOFs(field, extracted_field.getArray());
for (UInt i = 0; i < Parent::local_points * Dim; ++i)
LM_TOIMPLEMENT;
// extracted_field[i] *= -1;
}
/* do communication */
this->synchSumBuffer(Dim, extracted_field.getArray());
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::attachVector(
ContainerArray<Real> &tab) {
if (domA.getContainer().hasRefManager())
domA.getContainer().getRefManager()->attachVector(tab, this->pointList);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::checkPositionCoherency() {
if (this->in_group_B) {
// interpolate atomic sites to check everything is ok from this
typename DomainC::_Vec_ &field = domC.getP0();
UInt *assoc_tmp = &Parent::assoc[0];
for (UInt i = 0; i < Parent::local_points; ++i) {
{
Real x[3] = {0.0, 0.0, 0.0};
Vector<Dim> pos = VectorView<Dim>(&Parent::positions[Dim * i]);
for (UInt k = 0; k < Dim; ++k) {
x[k] = this->getShapeMatrix().interpolate(i, field, assoc_tmp[i], k);
if (x[k] != pos[k])
if (fabs(pos[k] - x[k]) > 1e-5) {
searchAtomInLocalPool(
static_cast<ContainerAtomsSubset &>(this->pointList), pos);
DUMP("mismatch in positions (X), atom "
<< i << " dist is " << pos[k] - x[k]
<< " : probably a redistribution trouble check "
"migrations\n"
<< "computed position is " << x[0] << " " << x[1] << " "
<< x[2] << " position was " << pos[0] << " " << pos[1]
<< " " << pos[2],
DBG_MESSAGE);
}
}
}
}
}
this->distributeVectorB2A("temp_positions", Parent::positions, Dim);
if (this->in_group_A) {
UInt i = 0;
UInt global_flag = 0;
for (auto &&at : this->pointList) {
UInt local_flag = 0;
Vector<Dim> pos = VectorView<Dim>(&Parent::positions[Dim * i]);
Vector<Dim> at_pos = at.position0();
for (UInt k = 0; k < Dim; ++k) {
if (pos[k] != at_pos[k])
if (!local_flag && fabs(pos[k] - at_pos[k]) > 1e-5) {
searchAtomInLocalPool(this->pointList, pos);
DUMP("mismatch in positions (X), atom "
<< i << " dist is "
<< Parent::positions[Dim * i] - at.position0()[0]
<< " : probably a redistribution trouble check migrations"
<< std::endl
<< "ref is " << at << "\nand send position is " << pos[0]
<< " " << pos[1] << " " << pos[2],
DBG_MESSAGE);
local_flag = 1;
global_flag = 1;
}
}
++i;
}
if (global_flag) {
Parent::getDuoVector().print("buggy-redistrib");
LM_FATAL("abort due to migration problem");
}
}
DUMP("position coherency OK", DBG_INFO);
}
/* -------------------------------------------------------------------------- */
template <typename DomainA, typename DomainC, UInt Dim>
void BridgingAtomicContinuum<DomainA, DomainC, Dim>::searchAtomInLocalPool(
typename Parent::ContainerPointsSubset &container, Vector<Dim> &x) {
UInt i = 0;
for (auto &&at : container) {
#ifdef TRACE_ATOM
auto pos = at.position0();
#endif
IF_COORD_EQUALS(pos, x) {
DUMP("actually searched atom is at ref " << at << " bridge index " << i,
DBG_MESSAGE);
break;
}
++i;
}
if (i == container.size())
DUMP("atom " << x[0] << " " << x[1] << " " << x[2] << " "
<< " not found locally : probably has migrated"
<< " or is simply lost !"
<< " NOT GOOD",
DBG_MESSAGE);
i = 0;
for (auto &&at : domA.getContainer()) {
#ifdef TRACE_ATOM
auto pos = at.position0();
#endif
IF_COORD_EQUALS(pos, x) {
DUMP("actually searched atom is at ref " << at << " bridge index " << i,
DBG_MESSAGE);
break;
}
++i;
}
if (i == domA.getContainer().size())
DUMP("atom not found locally : probably has migrated"
<< "or is simply lost !"
<< " NOT GOOD",
DBG_MESSAGE);
}
/* -------------------------------------------------------------------------- */
DECLARE_ATOMIC_CONTINUUM_TEMPLATE(BridgingAtomicContinuum)
__END_LIBMULTISCALE__

Event Timeline