2006-09-28 03:51:33 +08:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
2007-01-30 08:22:05 +08:00
|
|
|
http://lammps.sandia.gov, Sandia National Laboratories
|
|
|
|
Steve Plimpton, sjplimp@sandia.gov
|
2006-09-28 03:51:33 +08:00
|
|
|
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
2012-06-07 06:47:51 +08:00
|
|
|
certain rights in this software. This software is distributed under
|
2006-09-28 03:51:33 +08:00
|
|
|
the GNU General Public License.
|
|
|
|
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
2015-10-31 04:04:06 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2006-09-28 03:51:33 +08:00
|
|
|
#include "region_intersect.h"
|
|
|
|
#include "domain.h"
|
|
|
|
#include "error.h"
|
2013-06-29 03:00:58 +08:00
|
|
|
#include "force.h"
|
2006-09-28 03:51:33 +08:00
|
|
|
|
2007-01-30 08:22:05 +08:00
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
|
2006-09-28 03:51:33 +08:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
2007-01-30 08:22:05 +08:00
|
|
|
RegIntersect::RegIntersect(LAMMPS *lmp, int narg, char **arg) :
|
|
|
|
Region(lmp, narg, arg)
|
2006-09-28 03:51:33 +08:00
|
|
|
{
|
2011-09-24 02:06:55 +08:00
|
|
|
if (narg < 5) error->all(FLERR,"Illegal region command");
|
2013-06-29 03:00:58 +08:00
|
|
|
int n = force->inumeric(FLERR,arg[2]);
|
2011-09-24 02:06:55 +08:00
|
|
|
if (n < 2) error->all(FLERR,"Illegal region command");
|
2006-11-01 06:16:12 +08:00
|
|
|
options(narg-(n+3),&arg[n+3]);
|
|
|
|
|
2006-09-28 03:51:33 +08:00
|
|
|
// build list of regions to intersect
|
2013-08-02 22:38:49 +08:00
|
|
|
// store sub-region IDs in idsub
|
2006-09-28 03:51:33 +08:00
|
|
|
|
2013-08-02 22:38:49 +08:00
|
|
|
idsub = new char*[n];
|
2006-09-28 03:51:33 +08:00
|
|
|
list = new int[n];
|
|
|
|
nregion = 0;
|
|
|
|
|
2013-08-02 22:57:38 +08:00
|
|
|
int m,iregion;
|
2006-09-28 03:51:33 +08:00
|
|
|
for (int iarg = 0; iarg < n; iarg++) {
|
2013-08-02 22:57:38 +08:00
|
|
|
m = strlen(arg[iarg+3]) + 1;
|
|
|
|
idsub[nregion] = new char[m];
|
2013-08-02 22:38:49 +08:00
|
|
|
strcpy(idsub[nregion],arg[iarg+3]);
|
|
|
|
iregion = domain->find_region(idsub[nregion]);
|
2015-10-31 04:04:06 +08:00
|
|
|
if (iregion == -1)
|
2013-01-19 04:39:12 +08:00
|
|
|
error->all(FLERR,"Region intersect region ID does not exist");
|
2006-09-28 03:51:33 +08:00
|
|
|
list[nregion++] = iregion;
|
|
|
|
}
|
|
|
|
|
2014-12-20 08:02:43 +08:00
|
|
|
// this region is variable shape or dynamic if any of sub-regions are
|
2006-09-28 03:51:33 +08:00
|
|
|
|
|
|
|
Region **regions = domain->regions;
|
2014-12-20 08:02:43 +08:00
|
|
|
for (int ilist = 0; ilist < nregion; ilist++) {
|
2013-01-19 04:55:26 +08:00
|
|
|
if (regions[list[ilist]]->varshape) varshape = 1;
|
2014-12-20 08:02:43 +08:00
|
|
|
if (regions[list[ilist]]->dynamic) dynamic = 1;
|
|
|
|
}
|
2013-01-19 04:55:26 +08:00
|
|
|
|
|
|
|
// extent of intersection of regions
|
|
|
|
// has bounding box if interior and any sub-region has bounding box
|
2006-09-28 03:51:33 +08:00
|
|
|
|
2010-01-09 06:54:13 +08:00
|
|
|
bboxflag = 0;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++)
|
|
|
|
if (regions[list[ilist]]->bboxflag == 1) bboxflag = 1;
|
|
|
|
if (!interior) bboxflag = 0;
|
|
|
|
|
|
|
|
if (bboxflag) {
|
|
|
|
int first = 1;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++) {
|
|
|
|
if (regions[list[ilist]]->bboxflag == 0) continue;
|
|
|
|
if (first) {
|
2012-06-07 06:47:51 +08:00
|
|
|
extent_xlo = regions[list[ilist]]->extent_xlo;
|
|
|
|
extent_ylo = regions[list[ilist]]->extent_ylo;
|
|
|
|
extent_zlo = regions[list[ilist]]->extent_zlo;
|
|
|
|
extent_xhi = regions[list[ilist]]->extent_xhi;
|
|
|
|
extent_yhi = regions[list[ilist]]->extent_yhi;
|
|
|
|
extent_zhi = regions[list[ilist]]->extent_zhi;
|
|
|
|
first = 0;
|
2010-01-09 06:54:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
extent_xlo = MAX(extent_xlo,regions[list[ilist]]->extent_xlo);
|
|
|
|
extent_ylo = MAX(extent_ylo,regions[list[ilist]]->extent_ylo);
|
|
|
|
extent_zlo = MAX(extent_zlo,regions[list[ilist]]->extent_zlo);
|
|
|
|
extent_xhi = MIN(extent_xhi,regions[list[ilist]]->extent_xhi);
|
|
|
|
extent_yhi = MIN(extent_yhi,regions[list[ilist]]->extent_yhi);
|
|
|
|
extent_zhi = MIN(extent_zhi,regions[list[ilist]]->extent_zhi);
|
|
|
|
}
|
2006-09-28 03:51:33 +08:00
|
|
|
}
|
2010-01-09 06:54:13 +08:00
|
|
|
|
|
|
|
// possible contacts = sum of possible contacts in all sub-regions
|
|
|
|
|
|
|
|
cmax = 0;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++)
|
|
|
|
cmax += regions[list[ilist]]->cmax;
|
|
|
|
contact = new Contact[cmax];
|
2006-09-28 03:51:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
RegIntersect::~RegIntersect()
|
|
|
|
{
|
2013-08-02 22:38:49 +08:00
|
|
|
for (int ilist = 0; ilist < nregion; ilist++) delete [] idsub[ilist];
|
|
|
|
delete [] idsub;
|
2006-09-28 03:51:33 +08:00
|
|
|
delete [] list;
|
2010-01-09 06:54:13 +08:00
|
|
|
delete [] contact;
|
2006-09-28 03:51:33 +08:00
|
|
|
}
|
|
|
|
|
2013-01-19 04:55:26 +08:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void RegIntersect::init()
|
|
|
|
{
|
|
|
|
Region::init();
|
2013-08-02 22:38:49 +08:00
|
|
|
|
|
|
|
// re-build list of sub-regions in case other regions were deleted
|
|
|
|
// error if a sub-region was deleted
|
|
|
|
|
|
|
|
int iregion;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++) {
|
|
|
|
iregion = domain->find_region(idsub[ilist]);
|
2015-10-31 04:04:06 +08:00
|
|
|
if (iregion == -1)
|
2013-08-02 22:38:49 +08:00
|
|
|
error->all(FLERR,"Region union region ID does not exist");
|
|
|
|
list[ilist] = iregion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// init the sub-regions
|
|
|
|
|
2013-01-19 04:55:26 +08:00
|
|
|
Region **regions = domain->regions;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++)
|
|
|
|
regions[list[ilist]]->init();
|
|
|
|
}
|
|
|
|
|
2010-01-09 06:54:13 +08:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
inside = 1 if x,y,z is match() with all sub-regions
|
|
|
|
else inside = 0
|
|
|
|
------------------------------------------------------------------------- */
|
2006-09-28 03:51:33 +08:00
|
|
|
|
2010-01-12 04:25:07 +08:00
|
|
|
int RegIntersect::inside(double x, double y, double z)
|
2006-09-28 03:51:33 +08:00
|
|
|
{
|
|
|
|
int ilist;
|
|
|
|
Region **regions = domain->regions;
|
|
|
|
for (ilist = 0; ilist < nregion; ilist++)
|
|
|
|
if (!regions[list[ilist]]->match(x,y,z)) break;
|
|
|
|
|
2010-01-12 04:25:07 +08:00
|
|
|
if (ilist == nregion) return 1;
|
|
|
|
return 0;
|
2006-09-28 03:51:33 +08:00
|
|
|
}
|
2010-01-09 06:54:13 +08:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
compute contacts with interior of intersection of sub-regions
|
|
|
|
(1) compute contacts in each sub-region
|
|
|
|
(2) only keep a contact if surface point is match() to all other regions
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int RegIntersect::surface_interior(double *x, double cutoff)
|
|
|
|
{
|
|
|
|
int m,ilist,jlist,iregion,jregion,ncontacts;
|
|
|
|
double xs,ys,zs;
|
|
|
|
|
|
|
|
Region **regions = domain->regions;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
for (ilist = 0; ilist < nregion; ilist++) {
|
|
|
|
iregion = list[ilist];
|
2010-01-12 04:25:07 +08:00
|
|
|
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
|
2010-01-09 06:54:13 +08:00
|
|
|
for (m = 0; m < ncontacts; m++) {
|
|
|
|
xs = x[0] - regions[iregion]->contact[m].delx;
|
|
|
|
ys = x[1] - regions[iregion]->contact[m].dely;
|
|
|
|
zs = x[2] - regions[iregion]->contact[m].delz;
|
|
|
|
for (jlist = 0; jlist < nregion; jlist++) {
|
2012-06-07 06:47:51 +08:00
|
|
|
if (jlist == ilist) continue;
|
|
|
|
jregion = list[jlist];
|
|
|
|
if (!regions[jregion]->match(xs,ys,zs)) break;
|
2010-01-09 06:54:13 +08:00
|
|
|
}
|
|
|
|
if (jlist == nregion) {
|
2012-06-07 06:47:51 +08:00
|
|
|
contact[n].r = regions[iregion]->contact[m].r;
|
|
|
|
contact[n].delx = regions[iregion]->contact[m].delx;
|
|
|
|
contact[n].dely = regions[iregion]->contact[m].dely;
|
|
|
|
contact[n].delz = regions[iregion]->contact[m].delz;
|
|
|
|
n++;
|
2010-01-09 06:54:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-07 06:47:51 +08:00
|
|
|
|
2010-01-09 06:54:13 +08:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
compute contacts with interior of intersection of sub-regions
|
|
|
|
(1) flip interior/exterior flag of each sub-region
|
|
|
|
(2) compute contacts in each sub-region
|
|
|
|
(3) only keep a contact if surface point is not match() to all other regions
|
|
|
|
(4) flip interior/exterior flags back to original settings
|
|
|
|
this is effectively same algorithm as surface_interior() for RegUnion
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int RegIntersect::surface_exterior(double *x, double cutoff)
|
|
|
|
{
|
|
|
|
int m,ilist,jlist,iregion,jregion,ncontacts;
|
|
|
|
double xs,ys,zs;
|
|
|
|
|
|
|
|
Region **regions = domain->regions;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
for (ilist = 0; ilist < nregion; ilist++)
|
|
|
|
regions[list[ilist]]->interior ^= 1;
|
|
|
|
|
|
|
|
for (ilist = 0; ilist < nregion; ilist++) {
|
|
|
|
iregion = list[ilist];
|
2010-01-12 04:25:07 +08:00
|
|
|
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
|
2010-01-09 06:54:13 +08:00
|
|
|
for (m = 0; m < ncontacts; m++) {
|
|
|
|
xs = x[0] - regions[iregion]->contact[m].delx;
|
|
|
|
ys = x[1] - regions[iregion]->contact[m].dely;
|
|
|
|
zs = x[2] - regions[iregion]->contact[m].delz;
|
|
|
|
for (jlist = 0; jlist < nregion; jlist++) {
|
2012-06-07 06:47:51 +08:00
|
|
|
if (jlist == ilist) continue;
|
|
|
|
jregion = list[jlist];
|
|
|
|
if (regions[jregion]->match(xs,ys,zs)) break;
|
2010-01-09 06:54:13 +08:00
|
|
|
}
|
|
|
|
if (jlist == nregion) {
|
2012-06-07 06:47:51 +08:00
|
|
|
contact[n].r = regions[iregion]->contact[m].r;
|
|
|
|
contact[n].delx = regions[iregion]->contact[m].delx;
|
|
|
|
contact[n].dely = regions[iregion]->contact[m].dely;
|
|
|
|
contact[n].delz = regions[iregion]->contact[m].delz;
|
|
|
|
n++;
|
2010-01-09 06:54:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ilist = 0; ilist < nregion; ilist++)
|
|
|
|
regions[list[ilist]]->interior ^= 1;
|
2012-06-07 06:47:51 +08:00
|
|
|
|
2010-01-09 06:54:13 +08:00
|
|
|
return n;
|
|
|
|
}
|
2013-01-19 04:55:26 +08:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
change region shape of all sub-regions
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void RegIntersect::shape_update()
|
|
|
|
{
|
|
|
|
Region **regions = domain->regions;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++)
|
|
|
|
regions[list[ilist]]->shape_update();
|
|
|
|
}
|
2014-12-20 08:02:43 +08:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
move/rotate all sub-regions
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void RegIntersect::pretransform()
|
|
|
|
{
|
|
|
|
Region **regions = domain->regions;
|
|
|
|
for (int ilist = 0; ilist < nregion; ilist++)
|
|
|
|
regions[list[ilist]]->pretransform();
|
|
|
|
}
|