00001 #ifndef VIENNAFEM_TRANSFORM_HPP
00002 #define VIENNAFEM_TRANSFORM_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "viennafem/forwards.h"
00018 #include "viennafem/cell_quan.hpp"
00019
00020 #include "viennamath/expression.hpp"
00021 #include "viennamath/manipulation/substitute.hpp"
00022 #include "viennamath/manipulation/diff.hpp"
00023
00024 #include "viennagrid/topology/triangle.hpp"
00025 #include "viennagrid/topology/tetrahedron.hpp"
00026
00027
00032 namespace viennafem
00033 {
00034
00035 namespace detail
00036 {
00038 template <typename CellType, typename InterfaceType>
00039 void wrap_jacobian(viennafem::cell_quan<CellType, InterfaceType> & det_dF_dt, viennafem::unit_interval)
00040 {
00041 det_dF_dt.wrap_constant( viennafem::det_dF_dt_key() );
00042 }
00043
00045 template <typename CellType, typename InterfaceType>
00046 void wrap_jacobian(viennafem::cell_quan<CellType, InterfaceType> & det_dF_dt, viennafem::unit_triangle)
00047 {
00048 det_dF_dt.wrap_constant( viennafem::det_dF_dt_key() );
00049 }
00050
00052 template <typename CellType, typename InterfaceType>
00053 void wrap_jacobian(viennafem::cell_quan<CellType, InterfaceType> & det_dF_dt, viennafem::unit_tetrahedron)
00054 {
00055 det_dF_dt.wrap_constant( viennafem::det_dF_dt_key() );
00056 }
00057
00059 template <typename CellType, typename InterfaceType>
00060 void wrap_jacobian(viennafem::cell_quan<CellType, InterfaceType> & det_dF_dt, viennafem::unit_square)
00061 {
00062 det_dF_dt.wrap_expr( viennafem::det_dF_dt_key() );
00063 }
00064
00066 template <typename CellType, typename InterfaceType>
00067 void wrap_jacobian(viennafem::cell_quan<CellType, InterfaceType> & det_dF_dt, viennafem::unit_cube)
00068 {
00069 det_dF_dt.wrap_expr( viennafem::det_dF_dt_key() );
00070 }
00071
00073 template <typename CellType, typename InterfaceType, typename ReferenceCellTag>
00074 struct jacobian_adder : public viennamath::rt_manipulation_interface<InterfaceType>
00075 {
00076 public:
00077 typedef typename InterfaceType::numeric_type numeric_type;
00078
00079 InterfaceType * operator()(InterfaceType const * e) const
00080 {
00081 const viennamath::rt_unary_expr<InterfaceType> * integral_expression = dynamic_cast<const viennamath::rt_unary_expr<InterfaceType> *>(e);
00082
00083 if (integral_expression != NULL)
00084 {
00085 typedef viennamath::op_unary<viennamath::op_rt_symbolic_integral<InterfaceType>, InterfaceType> SymbolicIntegrationOperation;
00086
00087 const SymbolicIntegrationOperation * op_symb_tmp = dynamic_cast<const SymbolicIntegrationOperation *>(integral_expression->op());
00088
00089 viennafem::cell_quan<CellType, InterfaceType> det_dF_dt;
00090 detail::wrap_jacobian(det_dF_dt, ReferenceCellTag());
00091
00092 if (op_symb_tmp != NULL)
00093 {
00094 return new viennamath::rt_unary_expr<InterfaceType>(
00095 new viennamath::rt_binary_expr<InterfaceType>(integral_expression->lhs()->clone(),
00096 new viennamath::op_binary<viennamath::op_mult<numeric_type>, InterfaceType>(),
00097 det_dF_dt.clone()),
00098 op_symb_tmp->clone());
00099 }
00100 }
00101
00102 return e->clone();
00103 }
00104
00105 bool modifies(InterfaceType const * e) const
00106 {
00107 const viennamath::rt_unary_expr<InterfaceType> * integral_expression = dynamic_cast<const viennamath::rt_unary_expr<InterfaceType> *>(e);
00108
00109 if (integral_expression != NULL)
00110 {
00111 typedef viennamath::op_unary<viennamath::op_rt_symbolic_integral<InterfaceType>, InterfaceType> SymbolicIntegrationOperation;
00112
00113 const SymbolicIntegrationOperation * op_symb_tmp = dynamic_cast<const SymbolicIntegrationOperation *>(integral_expression->op());
00114
00115 if (op_symb_tmp != NULL)
00116 return true;
00117 }
00118 return false;
00119 }
00120 };
00121
00122
00123
00125 template <long i, long j, typename CellType, typename InterfaceType>
00126 void wrap_dt_dx(viennafem::cell_quan<CellType, InterfaceType> & dt_dx, viennafem::unit_interval)
00127 {
00128 dt_dx.wrap_constant( viennafem::dt_dx_key<i,j>() );
00129 }
00130
00132 template <long i, long j, typename CellType, typename InterfaceType>
00133 void wrap_dt_dx(viennafem::cell_quan<CellType, InterfaceType> & dt_dx, viennafem::unit_triangle)
00134 {
00135 dt_dx.wrap_constant( viennafem::dt_dx_key<i,j>() );
00136 }
00137
00139 template <long i, long j, typename CellType, typename InterfaceType>
00140 void wrap_dt_dx(viennafem::cell_quan<CellType, InterfaceType> & dt_dx, viennafem::unit_tetrahedron)
00141 {
00142 dt_dx.wrap_constant( viennafem::dt_dx_key<i,j>() );
00143 }
00144
00146 template <long i, long j, typename CellType, typename InterfaceType>
00147 void wrap_dt_dx(viennafem::cell_quan<CellType, InterfaceType> & dt_dx, viennafem::unit_square)
00148 {
00149 dt_dx.wrap_expr( viennafem::dt_dx_key<i,j>() );
00150 }
00151
00153 template <long i, long j, typename CellType, typename InterfaceType>
00154 void wrap_dt_dx(viennafem::cell_quan<CellType, InterfaceType> & dt_dx, viennafem::unit_cube)
00155 {
00156 dt_dx.wrap_expr( viennafem::dt_dx_key<i,j>() );
00157 }
00158
00160
00161
00162
00163
00165 template <typename CellType, typename EquationType, typename PDESystemType, typename ReferenceCellTag>
00166 EquationType transform_to_reference_cell_1d(EquationType const & weak_form,
00167 PDESystemType const & pde_system,
00168 ReferenceCellTag)
00169 {
00170 typedef typename EquationType::interface_type InterfaceType;
00171 typedef typename InterfaceType::numeric_type numeric_type;
00172 typedef viennamath::rt_function_symbol<InterfaceType> FunctionSymbol;
00173 typedef viennamath::rt_expr<InterfaceType> Expression;
00174 typedef viennamath::rt_unary_expr<InterfaceType> UnaryExpression;
00175 typedef viennamath::rt_variable<InterfaceType> Variable;
00176 typedef viennamath::op_unary<viennamath::op_partial_deriv<viennamath::default_numeric_type>, InterfaceType > d_dx;
00177
00178
00179
00180 FunctionSymbol u(0, viennamath::unknown_tag<>());
00181 FunctionSymbol v(0, viennamath::test_tag<>());
00182 Variable r(0);
00183
00184
00185 viennafem::cell_quan<CellType, InterfaceType> dr_dx; detail::wrap_dt_dx<0,0>(dr_dx, ReferenceCellTag());
00186
00187 Expression new_lhs = weak_form.lhs();
00188 Expression new_rhs = weak_form.rhs();
00189
00190
00191
00192
00193 std::vector<Expression> search_types(2);
00194 search_types[0] = UnaryExpression(u.clone(), new d_dx(0));
00195 search_types[1] = UnaryExpression(v.clone(), new d_dx(0));
00196
00197 std::vector<Expression> replace_types(2);
00198 replace_types[0] = viennamath::diff(u, r) * dr_dx;
00199 replace_types[1] = viennamath::diff(v, r) * dr_dx;
00200
00201
00202 new_lhs = viennamath::substitute(search_types, replace_types, weak_form.lhs());
00203 new_rhs = viennamath::substitute(search_types, replace_types, weak_form.rhs());
00204
00205 viennamath::rt_manipulation_wrapper<InterfaceType> jacobian_manipulator( new detail::jacobian_adder<CellType, InterfaceType, ReferenceCellTag>() );
00206 Expression new_lhs_with_jacobian(new_lhs.get()->recursive_manipulation(jacobian_manipulator));
00207 Expression new_rhs_with_jacobian(new_rhs.get()->recursive_manipulation(jacobian_manipulator));
00208
00209 return EquationType(new_lhs_with_jacobian, new_rhs_with_jacobian);
00210 }
00211
00212
00214
00215
00216
00217
00218
00220 template <typename CellType, typename EquationType, typename PDESystemType, typename ReferenceCellTag>
00221 EquationType transform_to_reference_cell_2d(EquationType const & weak_form,
00222 PDESystemType const & pde_system,
00223 ReferenceCellTag)
00224 {
00225 typedef typename EquationType::interface_type InterfaceType;
00226 typedef typename InterfaceType::numeric_type numeric_type;
00227 typedef viennamath::rt_function_symbol<InterfaceType> FunctionSymbol;
00228 typedef viennamath::rt_expr<InterfaceType> Expression;
00229 typedef viennamath::rt_unary_expr<InterfaceType> UnaryExpression;
00230 typedef viennamath::rt_variable<InterfaceType> Variable;
00231 typedef viennamath::op_unary<viennamath::op_partial_deriv<viennamath::default_numeric_type>, InterfaceType > d_dx;
00232
00233
00234
00235 FunctionSymbol u(0, viennamath::unknown_tag<>());
00236 FunctionSymbol v(0, viennamath::test_tag<>());
00237 Variable r(0);
00238 Variable s(1);
00239
00240
00241 viennafem::cell_quan<CellType, InterfaceType> dr_dx; detail::wrap_dt_dx<0,0>(dr_dx, ReferenceCellTag());
00242 viennafem::cell_quan<CellType, InterfaceType> ds_dx; detail::wrap_dt_dx<1,0>(ds_dx, ReferenceCellTag());
00243
00244 viennafem::cell_quan<CellType, InterfaceType> dr_dy; detail::wrap_dt_dx<0,1>(dr_dy, ReferenceCellTag());
00245 viennafem::cell_quan<CellType, InterfaceType> ds_dy; detail::wrap_dt_dx<1,1>(ds_dy, ReferenceCellTag());
00246
00247 Expression new_lhs = weak_form.lhs();
00248 Expression new_rhs = weak_form.rhs();
00249
00250
00251
00252
00253 std::vector<Expression> search_types(4);
00254 search_types[0] = UnaryExpression(u.clone(), new d_dx(0));
00255 search_types[1] = UnaryExpression(u.clone(), new d_dx(1));
00256 search_types[2] = UnaryExpression(v.clone(), new d_dx(0));
00257 search_types[3] = UnaryExpression(v.clone(), new d_dx(1));
00258
00259 std::vector<Expression> replace_types(4);
00260 replace_types[0] = viennamath::diff(u, r) * dr_dx + viennamath::diff(u, s) * ds_dx;
00261 replace_types[1] = viennamath::diff(u, r) * dr_dy + viennamath::diff(u, s) * ds_dy;
00262
00263 replace_types[2] = viennamath::diff(v, r) * dr_dx + viennamath::diff(v, s) * ds_dx;
00264 replace_types[3] = viennamath::diff(v, r) * dr_dy + viennamath::diff(v, s) * ds_dy;
00265
00266
00267 new_lhs = viennamath::substitute(search_types, replace_types, weak_form.lhs());
00268 new_rhs = viennamath::substitute(search_types, replace_types, weak_form.rhs());
00269
00270 viennamath::rt_manipulation_wrapper<InterfaceType> jacobian_manipulator( new detail::jacobian_adder<CellType, InterfaceType, ReferenceCellTag>() );
00271 Expression new_lhs_with_jacobian(new_lhs.get()->recursive_manipulation(jacobian_manipulator));
00272 Expression new_rhs_with_jacobian(new_rhs.get()->recursive_manipulation(jacobian_manipulator));
00273
00274 return EquationType(new_lhs_with_jacobian, new_rhs_with_jacobian);
00275 }
00276
00277
00278
00279
00281
00282
00283
00284
00286 template <typename CellType, typename EquationType, typename PDESystemType, typename ReferenceCellTag>
00287 EquationType transform_to_reference_cell_3d(EquationType const & weak_form,
00288 PDESystemType const & pde_system,
00289 ReferenceCellTag)
00290 {
00291 typedef typename EquationType::interface_type InterfaceType;
00292 typedef viennamath::rt_function_symbol<InterfaceType> FunctionSymbol;
00293 typedef viennamath::rt_expr<InterfaceType> Expression;
00294 typedef viennamath::rt_unary_expr<InterfaceType> UnaryExpression;
00295 typedef viennamath::rt_variable<InterfaceType> Variable;
00296 typedef viennamath::op_unary<viennamath::op_partial_deriv<viennamath::default_numeric_type>, InterfaceType > d_dx;
00297
00298
00299
00300
00301
00302 std::size_t num_components = pde_system.unknown(0).size();
00303 std::cout << "Number of components: " << num_components << std::endl;
00304 std::vector< FunctionSymbol > u(num_components);
00305 for (std::size_t i=0; i<num_components; ++i)
00306 u[i] = FunctionSymbol(pde_system.unknown(0)[i].id(), viennamath::unknown_tag<>());
00307
00308 std::vector< FunctionSymbol > v(num_components);
00309 for (std::size_t i=0; i<num_components; ++i)
00310 v[i] = FunctionSymbol(pde_system.unknown(0)[i].id(), viennamath::test_tag<>());
00311
00312 Variable r(0);
00313 Variable s(1);
00314 Variable t(2);
00315
00316
00317 viennafem::cell_quan<CellType, InterfaceType> dr_dx; detail::wrap_dt_dx<0,0>(dr_dx, ReferenceCellTag());
00318 viennafem::cell_quan<CellType, InterfaceType> ds_dx; detail::wrap_dt_dx<1,0>(ds_dx, ReferenceCellTag());
00319 viennafem::cell_quan<CellType, InterfaceType> dt_dx; detail::wrap_dt_dx<2,0>(dt_dx, ReferenceCellTag());
00320
00321 viennafem::cell_quan<CellType, InterfaceType> dr_dy; detail::wrap_dt_dx<0,1>(dr_dy, ReferenceCellTag());
00322 viennafem::cell_quan<CellType, InterfaceType> ds_dy; detail::wrap_dt_dx<1,1>(ds_dy, ReferenceCellTag());
00323 viennafem::cell_quan<CellType, InterfaceType> dt_dy; detail::wrap_dt_dx<2,1>(dt_dy, ReferenceCellTag());
00324
00325 viennafem::cell_quan<CellType, InterfaceType> dr_dz; detail::wrap_dt_dx<0,2>(dr_dz, ReferenceCellTag());
00326 viennafem::cell_quan<CellType, InterfaceType> ds_dz; detail::wrap_dt_dx<1,2>(ds_dz, ReferenceCellTag());
00327 viennafem::cell_quan<CellType, InterfaceType> dt_dz; detail::wrap_dt_dx<2,2>(dt_dz, ReferenceCellTag());
00328
00329 Expression new_lhs = weak_form.lhs();
00330 Expression new_rhs = weak_form.rhs();
00331
00332
00333 std::vector<Expression> search_types(2 * 3 * num_components);
00334 std::size_t current_index = 0;
00335 for (std::size_t i=0; i<num_components; ++i)
00336 {
00337 search_types[current_index++] = UnaryExpression(u[i].clone(), new d_dx(0));
00338 search_types[current_index++] = UnaryExpression(u[i].clone(), new d_dx(1));
00339 search_types[current_index++] = UnaryExpression(u[i].clone(), new d_dx(2));
00340
00341 search_types[current_index++] = UnaryExpression(v[i].clone(), new d_dx(0));
00342 search_types[current_index++] = UnaryExpression(v[i].clone(), new d_dx(1));
00343 search_types[current_index++] = UnaryExpression(v[i].clone(), new d_dx(2));
00344 }
00345
00346 std::vector<Expression> replace_types(2 * 3 * num_components);
00347 current_index = 0;
00348 for (std::size_t i=0; i<num_components; ++i)
00349 {
00350 replace_types[current_index++] = viennamath::diff(u[i], r) * dr_dx + viennamath::diff(u[i], s) * ds_dx + viennamath::diff(u[i], t) * dt_dx;
00351 replace_types[current_index++] = viennamath::diff(u[i], r) * dr_dy + viennamath::diff(u[i], s) * ds_dy + viennamath::diff(u[i], t) * dt_dy;
00352 replace_types[current_index++] = viennamath::diff(u[i], r) * dr_dz + viennamath::diff(u[i], s) * ds_dz + viennamath::diff(u[i], t) * dt_dz;
00353
00354 replace_types[current_index++] = viennamath::diff(v[i], r) * dr_dx + viennamath::diff(v[i], s) * ds_dx + viennamath::diff(v[i], t) * dt_dx;
00355 replace_types[current_index++] = viennamath::diff(v[i], r) * dr_dy + viennamath::diff(v[i], s) * ds_dy + viennamath::diff(v[i], t) * dt_dy;
00356 replace_types[current_index++] = viennamath::diff(v[i], r) * dr_dz + viennamath::diff(v[i], s) * ds_dz + viennamath::diff(v[i], t) * dt_dz;
00357 }
00358
00359
00360 new_lhs = viennamath::substitute(search_types, replace_types, weak_form.lhs());
00361 new_rhs = viennamath::substitute(search_types, replace_types, weak_form.rhs());
00362
00363 viennamath::rt_manipulation_wrapper<InterfaceType> jacobian_manipulator( new detail::jacobian_adder<CellType,
00364 InterfaceType,
00365 ReferenceCellTag>() );
00366 Expression new_lhs_with_jacobian(new_lhs.get()->recursive_manipulation(jacobian_manipulator));
00367 Expression new_rhs_with_jacobian(new_rhs.get()->recursive_manipulation(jacobian_manipulator));
00368
00369 return EquationType(new_lhs_with_jacobian, new_rhs_with_jacobian);
00370 }
00371
00372 }
00373
00374
00376
00377
00378
00379
00380
00382 template <typename CellType, typename EquationType, typename PDESystemType>
00383 EquationType transform_to_reference_cell(EquationType const & weak_form,
00384 PDESystemType const & pde_system,
00385 viennafem::unit_interval)
00386 {
00387 return detail::transform_to_reference_cell_1d<CellType>(weak_form, pde_system, viennafem::unit_interval());
00388 }
00389
00390
00391
00393 template <typename CellType, typename EquationType, typename PDESystemType>
00394 EquationType transform_to_reference_cell(EquationType const & weak_form,
00395 PDESystemType const & pde_system,
00396 viennafem::unit_square)
00397 {
00398 return detail::transform_to_reference_cell_2d<CellType>(weak_form, pde_system, viennafem::unit_square());
00399 }
00400
00402 template <typename CellType, typename EquationType, typename PDESystemType>
00403 EquationType transform_to_reference_cell(EquationType const & weak_form,
00404 PDESystemType const & pde_system,
00405 viennafem::unit_triangle)
00406 {
00407 return detail::transform_to_reference_cell_2d<CellType>(weak_form, pde_system, viennafem::unit_triangle());
00408 }
00409
00410
00411
00413 template <typename CellType, typename EquationType, typename PDESystemType>
00414 EquationType transform_to_reference_cell(EquationType const & weak_form,
00415 PDESystemType const & pde_system,
00416 viennafem::unit_cube)
00417 {
00418 return detail::transform_to_reference_cell_3d<CellType>(weak_form, pde_system, viennafem::unit_cube());
00419 }
00420
00422 template <typename CellType, typename EquationType, typename PDESystemType>
00423 EquationType transform_to_reference_cell(EquationType const & weak_form,
00424 PDESystemType const & pde_system,
00425 viennafem::unit_tetrahedron)
00426 {
00427 return detail::transform_to_reference_cell_3d<CellType>(weak_form, pde_system, viennafem::unit_tetrahedron());
00428 }
00429
00430
00431
00433 template <typename CellType, typename EquationType, typename PDESystemType>
00434 EquationType transform_to_reference_cell(EquationType const & weak_form,
00435 PDESystemType const & pde_system)
00436 {
00437 typedef typename CellType::tag CellTag;
00438
00439 return transform_to_reference_cell<CellType>(weak_form,
00440 pde_system,
00441 typename reference_cell_for_basis<CellTag, viennafem::lagrange_tag<1> >::type());
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00452
00453
00454
00465 template <typename EquationType, typename PDESystemType, typename ExpressionType>
00466 EquationType insert_test_and_trial_functions(EquationType weak_form,
00467 PDESystemType const & pde_system,
00468 std::vector<ExpressionType> test_func,
00469 std::vector<ExpressionType> trial_func
00470 )
00471 {
00472 typedef typename EquationType::interface_type InterfaceType;
00473 typedef viennamath::rt_expr<InterfaceType> Expression;
00474 typedef viennamath::rt_function_symbol<InterfaceType> FunctionSymbol;
00475 typedef viennamath::rt_unary_expr<InterfaceType> UnaryExpression;
00476 typedef viennamath::rt_variable<InterfaceType> Variable;
00477 typedef viennamath::op_unary<viennamath::op_partial_deriv<viennamath::default_numeric_type>, InterfaceType > d_dx;
00478
00479 std::vector< FunctionSymbol > u(trial_func.size());
00480 for (std::size_t i=0; i<trial_func.size(); ++i)
00481 u[i] = FunctionSymbol(pde_system.unknown(0)[i].id(), viennamath::unknown_tag<>());
00482
00483 std::vector< FunctionSymbol > v(test_func.size());
00484 for (std::size_t i=0; i<test_func.size(); ++i)
00485 v[i] = FunctionSymbol(pde_system.unknown(0)[i].id(), viennamath::test_tag<>());
00486
00487 Variable r(0);
00488 Variable s(1);
00489 Variable t(2);
00490
00491 std::vector<Expression> search_keys(4 * (test_func.size() + trial_func.size()));
00492 std::size_t current_index = 0;
00493 for (std::size_t i=0; i<trial_func.size(); ++i)
00494 {
00495 search_keys[current_index++] = UnaryExpression(u[i].clone(), new d_dx(0));
00496 search_keys[current_index++] = UnaryExpression(u[i].clone(), new d_dx(1));
00497 search_keys[current_index++] = UnaryExpression(u[i].clone(), new d_dx(2));
00498 search_keys[current_index++] = u[i];
00499 }
00500
00501 for (std::size_t i=0; i<test_func.size(); ++i)
00502 {
00503 search_keys[current_index++] = UnaryExpression(v[i].clone(), new d_dx(0));
00504 search_keys[current_index++] = UnaryExpression(v[i].clone(), new d_dx(1));
00505 search_keys[current_index++] = UnaryExpression(v[i].clone(), new d_dx(2));
00506 search_keys[current_index++] = v[i];
00507 }
00508
00509
00510 std::vector<Expression> replacements(4 * (test_func.size() + trial_func.size()));
00511 current_index = 0;
00512 for (std::size_t i=0; i<trial_func.size(); ++i)
00513 {
00514 replacements[current_index++] = viennamath::diff(trial_func[i], r);
00515 replacements[current_index++] = viennamath::diff(trial_func[i], s);
00516 replacements[current_index++] = viennamath::diff(trial_func[i], t);
00517 replacements[current_index++] = trial_func[i];
00518 }
00519
00520 for (std::size_t i=0; i<test_func.size(); ++i)
00521 {
00522 replacements[current_index++] = viennamath::diff(test_func[i], r);
00523 replacements[current_index++] = viennamath::diff(test_func[i], s);
00524 replacements[current_index++] = viennamath::diff(test_func[i], t);
00525 replacements[current_index++] = test_func[i];
00526 }
00527
00528 ExpressionType new_lhs = viennamath::substitute(search_keys, replacements, weak_form.lhs());
00529 ExpressionType new_rhs = viennamath::substitute(search_keys, replacements, weak_form.rhs());
00530
00531
00532
00533
00534 return EquationType(new_lhs, new_rhs);
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 }
00632 #endif