Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Andreas Vogel
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__LIB_DISC__SPATIAL_DISC__DATA_IMPORT_IMPL__
34 : #define __H__UG__LIB_DISC__SPATIAL_DISC__DATA_IMPORT_IMPL__
35 :
36 : #include "data_import.h"
37 :
38 : namespace ug{
39 :
40 : ////////////////////////////////////////////////////////////////////////////////
41 : // DataImport
42 : ////////////////////////////////////////////////////////////////////////////////
43 :
44 : template <typename TData, int dim>
45 0 : DataImport<TData,dim>::~DataImport()
46 : {
47 0 : if(data_given()) m_spUserData->unregister_storage_callback(this);
48 0 : }
49 :
50 : template <typename TData, int dim>
51 0 : void DataImport<TData,dim>::set_roid(ReferenceObjectID id)
52 : {
53 0 : if(id == ROID_UNKNOWN)
54 0 : UG_THROW("DataImport::set_roid: Setting unknown ReferenceObjectId.");
55 :
56 0 : m_id = id;
57 0 : }
58 :
59 : template <typename TData, int dim>
60 0 : void DataImport<TData,dim>::check_setup()
61 : {
62 : // if lin defect is not supposed to be computed, we're done
63 0 : if(!this->m_bCompLinDefect) return;
64 :
65 0 : if(m_id == ROID_UNKNOWN)
66 0 : UG_THROW("DataImport::check_setup: The reference element "
67 : "type has not been set for evaluation.");
68 :
69 : // Check for evaluation function and choose it if present
70 0 : if(m_vLinDefectFunc[m_id] != NULL)
71 : return;
72 :
73 : // fails
74 0 : UG_THROW("DataImport::check_setup: No evaluation function for computation of "
75 : "linearized defect registered for "<<m_id<<", but required. "
76 : "(world dim: "<<dim<<", part: "<<this->part()<<")");
77 : }
78 :
79 : template <typename TData, int dim>
80 : template <typename TClass>
81 : void
82 0 : DataImport<TData,dim>::
83 : set_fct(ReferenceObjectID id, TClass* obj,
84 : void (TClass::*func)(const LocalVector& u,
85 : std::vector<std::vector<TData> > vvvLinDefect[],
86 : const size_t nip))
87 : {
88 0 : if(id >= NUM_REFERENCE_OBJECTS)
89 0 : UG_THROW("Reference Object id invalid: "<<id);
90 :
91 0 : m_vLinDefectFunc[id] = std::bind(func, obj,
92 : std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
93 0 : }
94 :
95 : template <typename TData, int dim>
96 : void
97 : DataImport<TData,dim>::
98 : set_fct(ReferenceObjectID id,
99 : void (*func)(const LocalVector& u,
100 : std::vector<std::vector<TData> > vvvLinDefect[],
101 : const size_t nip))
102 : {
103 : if(id >= NUM_REFERENCE_OBJECTS)
104 : UG_THROW("Reference Object id invalid: "<<id);
105 :
106 : m_vLinDefectFunc[id] = func;
107 : }
108 :
109 : template <typename TData, int dim>
110 : void DataImport<TData,dim>::clear_fct()
111 : {
112 0 : for(size_t i = 0; i < NUM_REFERENCE_OBJECTS; ++i)
113 : m_vLinDefectFunc[i] = NULL;
114 : }
115 :
116 :
117 : template <typename TData, int dim>
118 0 : void DataImport<TData,dim>::set_data(SmartPtr<CplUserData<TData, dim> > spData)
119 : {
120 : // remember UserData
121 0 : m_spUserData = spData;
122 :
123 : // remember iexport
124 0 : this->m_spICplUserData = spData;
125 :
126 : // remember dependent data (i.e. is NULL iff no dependent data given)
127 0 : m_spDependentUserData = m_spUserData.template cast_dynamic<DependentUserData<TData, dim> >();
128 0 : }
129 :
130 : template <typename TData, int dim>
131 0 : void DataImport<TData,dim>::cache_data_access()
132 : {
133 : // cache the pointer to the data field.
134 0 : m_vValue = m_spUserData->values(m_seriesID);
135 :
136 : // in addition we cache the number of ips
137 0 : m_numIP = m_spUserData->num_ip(m_seriesID);
138 0 : }
139 :
140 : template <typename TData, int dim>
141 : template <int ldim>
142 0 : void DataImport<TData,dim>::set_local_ips(const MathVector<ldim>* vPos, size_t numIP, int timePointSpec,
143 : bool bMayChange)
144 : {
145 : // if no data set, skip
146 0 : if(!data_given()) return;
147 :
148 : // request series if first time requested
149 0 : if(m_seriesID == -1)
150 : {
151 0 : m_seriesID = m_spUserData->template
152 0 : register_local_ip_series<ldim>(vPos,numIP,timePointSpec,bMayChange);
153 :
154 : // register callback, invoked when data field is changed
155 0 : m_spUserData->register_storage_callback(this, &DataImport<TData,dim>::cache_data_access);
156 :
157 : // cache access to the data
158 : cache_data_access();
159 :
160 : // resize also lin defect array
161 0 : resize_defect_array();
162 :
163 : // check that num ip is correct
164 : UG_ASSERT(m_numIP == numIP, "Different number of ips than requested.");
165 : }
166 : else
167 : {
168 0 : if(!bMayChange)
169 0 : UG_THROW("DataImport: Setting different local ips to non-changable ip series.");
170 :
171 : // set new local ips
172 0 : m_spUserData->template set_local_ips<ldim>(m_seriesID,vPos,numIP);
173 0 : m_spUserData->set_time_point(m_seriesID,timePointSpec);
174 :
175 0 : if(numIP != m_numIP)
176 : {
177 : // cache access to the data
178 : cache_data_access();
179 :
180 : // resize also lin defect array
181 0 : resize_defect_array();
182 : }
183 :
184 : // check that num ip is correct
185 : UG_ASSERT(m_numIP == numIP, "Different number of ips than requested.");
186 : }
187 : }
188 :
189 : template <typename TData, int dim>
190 : void DataImport<TData,dim>::set_local_ips(const MathVector<dim>* vPos, size_t numIP, int timePointSpec,
191 : bool bMayChange)
192 : {
193 : set_local_ips<dim>(vPos, numIP, timePointSpec, bMayChange);
194 : }
195 :
196 : template <typename TData, int dim>
197 : template <int ldim>
198 : void DataImport<TData,dim>::set_local_ips(const MathVector<ldim>* vPos, size_t numIP,
199 : bool bMayChange)
200 : {
201 0 : set_local_ips<ldim>(vPos, numIP, -1, bMayChange);
202 : }
203 :
204 : template <typename TData, int dim>
205 : void DataImport<TData,dim>::set_local_ips(const MathVector<dim>* vPos, size_t numIP,
206 : bool bMayChange)
207 : {
208 0 : set_local_ips<dim>(vPos, numIP, -1, bMayChange);
209 : }
210 :
211 : template <typename TData, int dim>
212 : void DataImport<TData,dim>::set_time_point(int timePointSpec)
213 : {
214 : m_spUserData->set_time_point(m_seriesID,timePointSpec);
215 : }
216 :
217 : template <typename TData, int dim>
218 0 : void DataImport<TData,dim>::set_global_ips(const MathVector<dim>* vPos, size_t numIP)
219 : {
220 : // if no data set, skip
221 0 : if(!data_given()) return;
222 :
223 : // set global ips for series ID
224 : UG_ASSERT(m_seriesID >= 0, "Wrong series id.");
225 0 : m_spUserData->set_global_ips(m_seriesID,vPos,numIP);
226 : }
227 :
228 : template <typename TData, int dim>
229 0 : void DataImport<TData,dim>::clear_ips()
230 : {
231 0 : if(data_given()) m_spUserData->unregister_storage_callback(this);
232 0 : m_seriesID = -1;
233 0 : m_vValue = 0;
234 0 : m_numIP = 0;
235 0 : m_vvvLinDefect.resize(num_ip());
236 0 : }
237 :
238 : template <typename TData, int dim>
239 0 : void DataImport<TData,dim>::add_jacobian(LocalMatrix& J, const number scale)
240 : {
241 : UG_ASSERT(m_spDependentUserData.valid(), "No Export set.");
242 :
243 : /// compute the linearization only if the export parameter is 'at current time'
244 0 : if (! m_spUserData->at_current_time (m_seriesID))
245 : return;
246 :
247 : // access jacobian by maps
248 0 : J.access_by_map(this->map(), this->conn_map());
249 :
250 : // loop integration points
251 0 : for(size_t ip = 0; ip < num_ip(); ++ip)
252 : {
253 : // loop all functions
254 0 : for(size_t fct1 = 0; fct1 < this->num_fct(); ++fct1)
255 0 : for(size_t fct2 = 0; fct2 < m_spDependentUserData->num_fct(); ++fct2)
256 : {
257 : // get array of linearized defect and derivative
258 : const TData* LinDef = lin_defect(ip, fct1);
259 : const TData* Deriv = m_spDependentUserData->deriv(m_seriesID, ip, fct2);
260 :
261 : // loop shapes of functions
262 0 : for(size_t sh1 = 0; sh1 < num_sh(fct1); ++sh1)
263 0 : for(size_t sh2 = 0; sh2 < m_spDependentUserData->num_sh(fct2); ++sh2)
264 : {
265 0 : J(fct1, sh1, fct2, sh2) += scale*(LinDef[sh1]*Deriv[sh2]);
266 : }
267 : }
268 : }
269 : }
270 :
271 : template <typename TData, int dim>
272 0 : void DataImport<TData,dim>::update_dof_sizes(const LocalIndices& ind)
273 : {
274 : // check size
275 : const FunctionIndexMapping& map = this->map();
276 : UG_ASSERT(map.num_fct() == this->num_fct(), "Number function mismatch.");
277 :
278 : // cache numFct and their numDoFs
279 0 : m_vvNumDoFPerFct.resize(map.num_fct());
280 0 : for(size_t fct = 0; fct < m_vvNumDoFPerFct.size(); ++fct)
281 0 : m_vvNumDoFPerFct[fct] = ind.num_dof(map[fct]);
282 :
283 : m_vvvLinDefect.clear();
284 0 : resize_defect_array();
285 0 : }
286 :
287 : template <typename TData, int dim>
288 0 : void DataImport<TData,dim>::resize_defect_array()
289 : {
290 : // get old size
291 : // NOTE: for all ips up to oldSize the arrays are already resized
292 : const size_t oldSize = m_vvvLinDefect.size();
293 :
294 : // resize ips
295 0 : m_vvvLinDefect.resize(num_ip());
296 :
297 : // resize num fct
298 0 : for(size_t ip = oldSize; ip < num_ip(); ++ip)
299 : {
300 : // resize num fct
301 0 : m_vvvLinDefect[ip].resize(m_vvNumDoFPerFct.size());
302 :
303 : // resize dofs
304 0 : for(size_t fct = 0; fct < m_vvNumDoFPerFct.size(); ++fct)
305 0 : m_vvvLinDefect[ip][fct].resize(m_vvNumDoFPerFct[fct]);
306 : }
307 0 : }
308 :
309 : template <typename TData, int dim>
310 : inline void DataImport<TData,dim>::check_ip_fct(size_t ip, size_t fct) const
311 : {
312 : check_ip(ip);
313 : UG_ASSERT(ip < m_vvvLinDefect.size(), "Invalid index.");
314 : UG_ASSERT(fct < m_vvvLinDefect[ip].size(), "Invalid index.");
315 : }
316 :
317 : template <typename TData, int dim>
318 : inline void DataImport<TData,dim>::check_ip_fct_sh(size_t ip, size_t fct, size_t sh) const
319 : {
320 : check_ip_fct(ip, fct);
321 : UG_ASSERT(sh < m_vvvLinDefect[ip][fct].size(), "Invalid index.");
322 : }
323 :
324 : template <typename TData, int dim>
325 : inline void DataImport<TData,dim>::check_ip(size_t ip) const
326 : {
327 : UG_ASSERT(ip < m_numIP, "Invalid index.");
328 : }
329 :
330 : template <typename TData, int dim>
331 : inline void DataImport<TData,dim>::check_values() const
332 : {
333 : UG_ASSERT(m_vValue != NULL, "Data Value field not set.");
334 : }
335 :
336 : } // end namespace ug
337 :
338 : #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__DATA_IMPORT_IMPL__ */
|