OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
uniformgridfield.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include <cassert>
36 #include <cmath>
37 #include "uniformgridfield.h"
38 #include "dofmanager.h"
39 #include "error.h"
40 
41 #include <iostream>
42 
43 namespace oofem {
44 
45 // inspired by https://github.com/woodem/woo/blob/master/pkg/dem/FlowAnalysis.hpp#L20
46 // returns lo-indices of containing cell (clamped to domain)
47 // and also computes normalized (0…1)×..×(0…1) coords within that cell
48 void UniformGridField::xyz2ijk(const FloatArray& xyz, IntArray& ijk, FloatArray& normXyz) const {
49  assert(xyz.giveSize()<=lo.giveSize());
50  assert(hi.giveSize()==lo.giveSize());
51  assert(div.giveSize()==lo.giveSize());
52  ijk.resize(xyz.giveSize());
53  normXyz.resize(xyz.giveSize());
54  for(int ax=0; ax<xyz.giveSize(); ax++){
55  // FIXME: cellDim should be cached and not computed over and over
56  double cellDim=(hi[ax]-lo[ax])/div[ax];
57  double t=(xyz[ax]-lo[ax])/cellDim;
58  // clamp to grid size
59  if(t>=div[ax]){ ijk[ax]=div[ax]-1; normXyz[ax]=1.; }
60  else if(t<0) { ijk[ax]=0; normXyz[ax]=0.; }
61  else { ijk[ax]=(int)std::floor(t); normXyz[ax]=t-ijk[ax]; }
62  }
63 }
64 
65 void UniformGridField::setGeometry(const FloatArray& lo_, const FloatArray& hi_, const IntArray& div_){
66  // std::cerr<<"lo dimension: "<<lo.giveSize()<<std::endl;
67  if(lo_.giveSize()!=hi_.giveSize()) OOFEM_ERROR("lo and hi must have identical dimension.");
68  if(lo_.giveSize()!=div_.giveSize()) OOFEM_ERROR("lo and div must have identical dimension.");
69  if(lo_.giveSize()!=2 && lo_.giveSize()!=3) OOFEM_ERROR("Dimension must be 2 or 3.");
70  for(int i=0; i<lo_.giveSize(); i++){
71  if(lo_[i]>=hi_[i]) OOFEM_ERROR("lo must be strictly smaller than hi along all axes.");
72  if(div_[i]<1) OOFEM_ERROR("div must be at least 1 along all axes.")
73  }
74  lo=lo_;
75  hi=hi_;
76  div=div_;
77  #if 0
78  this->precomputeInternal();
79  #endif
80 }
82  int s=1;
83  for(int i=0; i<div.giveSize(); i++) s*=div[i]+1;
84  if(vv.giveSize()!=s) OOFEM_ERROR((std::string("Array size must be exactly prod(div[i]+1)=")+std::to_string(s)).c_str());
85  values=vv;
86 }
87 
88 double UniformGridField::nodeValue2d(int i, int j){
89  assert(div.giveSize()==2);
90  assert(values.giveSize()==(div[0]+1)*(div[1]+1));
91  return values[(div[1]+1)*i+j];
92 }
93 
94 double UniformGridField::nodeValue3d(int i, int j, int k){
95  assert(div.giveSize()==3);
96  assert(values.giveSize()==(div[0]+1)*(div[1]+1)*(div[2]+1));
97  return values[(div[2]+1)*(div[1]+1)*i+(div[2]+1)*j+k];
98 }
99 
100 // see https://github.com/woodem/woo/blob/master/pkg/dem/FlowAnalysis.cpp
101 // and https://woodem.org/user/flow-analysis.html for explanation about the interpolation routine
103  ValueModeType mode, TimeStep *tStep){
104  // scalar value
105  answer.resize(1);
106  double& ret(answer[0]);
107  ret=0;
108 
109  // find cell containing coords, and coords within the cell
110  IntArray ijk; FloatArray normXyz;
111  this->xyz2ijk(coords,ijk,normXyz);
112 
113  // 3D interpolation
114  if(ijk.giveSize()==3){
115  const int& i(ijk[0]); const int& j(ijk[1]); const int& k(ijk[2]);
116  int I(i+1), J(j+1), K(k+1);
117  const double& x(normXyz[0]); const double& y(normXyz[1]); const double& z(normXyz[2]);
118  double X(1-x), Y(1-y), Z(1-z);
119  double weights[]={
120  X*Y*Z,x*Y*Z,x*y*Z,X*y*Z,
121  X*Y*z,x*Y*z,x*y*z,X*y*z
122  };
123  int pts[][3]={
124  {i,j,k},{I,j,k},{I,J,k},{i,J,k},
125  {i,j,K},{I,j,K},{I,J,K},{i,J,K}
126  };
127  assert(abs(weights[0]+weights[1]+weights[2]+weights[3]+weights[4]+weights[5]+weights[6]+weights[7]-1) < 1e-5);
128  for(int p=0; p<8; p++){
129  // std::cerr<<p<<": at "<<coords[0]<<","<<coords[1]<<","<<coords[2]<<", ijk "<<i<<","<<j<<","<<k<<" normXYZ "<<x<<","<<y<<","<<z<<std::endl;
130  ret+=weights[p]*this->nodeValue3d(pts[p][0],pts[p][1],pts[p][2]);
131  }
132  }
133  // 2D interpolation
134  else if (ijk.giveSize()==2){
135  const int& i(ijk[0]); const int& j(ijk[1]); int I(i+1); int J(j+1);
136  const double& x(normXyz[0]); const double y(normXyz[1]); double X(1-x); double Y(1-y);
137  double weights[]={X*Y,x*Y,X*y,x*y}; // TODO: check
138  int pts[][2]={{i,j},{I,j},{i,J},{I,J}}; // TODO: check
139  assert(abs(weights[0]+weights[1]+weights[2]+weights[3]-1)<1e-5);
140  for(int p=0; p<4; p++){
141  // std::cerr<<p<<": at "<<coords[0]<<","<<coords[1]<<" ij "<<i<<","<<j<<" normXY "<<x<<","<<y<<std::endl;
142  ret+=weights[p]*this->nodeValue2d(pts[p][0],pts[p][1]);
143  }
144  }
145  // any other is unsupported
146  else {
147  OOFEM_ERROR((std::string("UniformGridField::evaluateAt: erroneous dimension of input coordinates (")+std::to_string(coords.giveSize())+", must be 2 or 3).").c_str());
148  return 1;
149  }
150 
151  return 0; // OK
152 }
153 
154 
155 
156 int
158 {
159  if ( dman->hasCoordinates()) {
160  int result=evaluateAt(answer,*(dman->giveCoordinates()),mode,tStep);
161  return ( result == 1 );
162  }
163  // failed -> dman without coordinates
164  return 1;
165 }
166 
167 
168 
169 } // end namespace oofem
double nodeValue3d(int i, int j, int k)
void xyz2ijk(const FloatArray &xyz, IntArray &ijk, FloatArray &normXyz) const
ValueModeType
Type representing the mode of UnknownType or CharType, or similar types.
Definition: valuemodetype.h:78
virtual FloatArray * giveCoordinates()
Definition: dofmanager.h:382
Base class for dof managers.
Definition: dofmanager.h:113
Class implementing an array of integers.
Definition: intarray.h:61
int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override
Implementation of Field::evaluateAt for coordinates.
virtual bool hasCoordinates()
Definition: dofmanager.h:378
#define OOFEM_ERROR(...)
Definition: error.h:61
void setGeometry(const FloatArray &lo_, const FloatArray &hi_, const IntArray &div_)
Shorthand for defining geometry, with consistency checks.
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
void setValues(const FloatArray &vv)
Accessor for setting nodal values; checks size of the array for correctness.
Class representing vector of real numbers.
Definition: floatarray.h:82
double nodeValue2d(int i, int j)
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
Class representing solution step.
Definition: timestep.h:80
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:32 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011