OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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
43namespace 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
48void 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
65void 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 if (div_.giveSize()==2){
81 this->valueList.resize(div_.at(1)*div_.at(2));
82 } else {
83 this->valueList.resize(div_.at(1)*div_.at(2)*div_.at(3));
84 }
85}
86void UniformGridField::setValues(const std::vector< FloatArray > &vv){
87 int s=1;
88 for(int i=0; i<div.giveSize(); i++){
89 s*=div[i]+1;
90 }
91// if(vv.giveSize()!=s) OOFEM_ERROR((std::string("Array size must be exactly prod(div[i]+1)=")+std::to_string(s)).c_str());
92 valueList=vv;
93
94
95}
96
98 assert(div.giveSize()==2);
99 assert(valueList.size()==(long unsigned int)(div[0]+1)*(div[1]+1));
100 return valueList[(div[1]+1)*i+j];
101}
102
103const FloatArray UniformGridField::nodeValue3d(int i, int j, int k){
104 assert(div.giveSize()==3);
105 assert(valueList.size()==(long unsigned int)(div[0]+1)*(div[1]+1)*(div[2]+1));
106 return valueList[(div[2]+1)*(div[1]+1)*i+(div[2]+1)*j+k];
107}
108
109// see https://github.com/woodem/woo/blob/master/pkg/dem/FlowAnalysis.cpp
110// and https://woodem.org/user/flow-analysis.html for explanation about the interpolation routine
112 ValueModeType mode, TimeStep *tStep){
113 // scalar value
114 FloatArray ret(valueList[0]);
115 ret.zero();
116
117 // find cell containing coords, and coords within the cell
118 IntArray ijk; FloatArray normXyz;
119 this->xyz2ijk(coords,ijk,normXyz);
120
121 // 3D interpolation
122 if(ijk.giveSize()==3){
123 const int& i(ijk[0]); const int& j(ijk[1]); const int& k(ijk[2]);
124 int I(i+1), J(j+1), K(k+1);
125 const double& x(normXyz[0]); const double& y(normXyz[1]); const double& z(normXyz[2]);
126 double X(1-x), Y(1-y), Z(1-z);
127 double weights[]={
128 X*Y*Z,x*Y*Z,x*y*Z,X*y*Z,
129 X*Y*z,x*Y*z,x*y*z,X*y*z
130 };
131 int pts[][3]={
132 {i,j,k},{I,j,k},{I,J,k},{i,J,k},
133 {i,j,K},{I,j,K},{I,J,K},{i,J,K}
134 };
135 assert(fabs(weights[0]+weights[1]+weights[2]+weights[3]+weights[4]+weights[5]+weights[6]+weights[7]-1) < 1e-5);
136 for(int p=0; p<8; p++){
137 // std::cerr<<p<<": at "<<coords[0]<<","<<coords[1]<<","<<coords[2]<<", ijk "<<i<<","<<j<<","<<k<<" normXYZ "<<x<<","<<y<<","<<z<<std::endl;
138 ret+=weights[p]*this->nodeValue3d(pts[p][0],pts[p][1],pts[p][2]);
139 }
140 }
141 // 2D interpolation
142 else if (ijk.giveSize()==2){
143 const int& i(ijk[0]); const int& j(ijk[1]); int I(i+1); int J(j+1);
144 const double& x(normXyz[0]); const double y(normXyz[1]); double X(1-x); double Y(1-y);
145 double weights[]={X*Y,x*Y,X*y,x*y}; // TODO: check
146 int pts[][2]={{i,j},{I,j},{i,J},{I,J}}; // TODO: check
147 assert(fabs(weights[0]+weights[1]+weights[2]+weights[3]-1)<1e-5);
148 for(int p=0; p<4; p++){
149 // std::cerr<<p<<": at "<<coords[0]<<","<<coords[1]<<" ij "<<i<<","<<j<<" normXY "<<x<<","<<y<<std::endl;
150 ret+=weights[p]*this->nodeValue2d(pts[p][0],pts[p][1]);
151 }
152 }
153 // any other is unsupported
154 else {
155 OOFEM_ERROR("%s",(std::string("UniformGridField::evaluateAt: erroneous dimension of input coordinates (")+std::to_string(coords.giveSize())+", must be 2 or 3).").c_str());
156 return 1;
157 }
158 answer = ret;
159 return 0; // OK
160}
161
162
163
164int
165UniformGridField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep)
166{
167 return evaluateAt(answer, dman->giveCoordinates(), mode, tStep) == 1;
168}
169
170
171
172} // end namespace oofem
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
void resize(Index s)
Definition floatarray.C:94
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
void setGeometry(const FloatArray &lo_, const FloatArray &hi_, const IntArray &div_)
const FloatArray nodeValue2d(int i, int j)
void setValues(const std::vector< FloatArray > &vv)
void xyz2ijk(const FloatArray &xyz, IntArray &ijk, FloatArray &normXyz) const
int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override
const FloatArray nodeValue3d(int i, int j, int k)
std::vector< FloatArray > valueList
#define OOFEM_ERROR(...)
Definition error.h:79

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011