Giter Club home page Giter Club logo

dealii-adapter's Introduction

deal.II-preCICE adapter

Building

Coupled structural solvers written with the C++ finite element library deal.II:

  • source/linear_elasticity contains a linear-elastic solver based on the step-8 tutorial program of deal.II
  • source/nonlinear_elasticity contains a nonlinear elastic solver, which builds on previous work of Jean-Paul Pelteret and Andrew McBride in their deal.II code gallery program 'Quasi-Static Finite-Strain Compressible Elasticity.' This solver supports shared-memory parallelization.

Applied coupling functionalities have been separated and can be found in the include/adapter directory.

Start here

Our documentation will help you start. If you are missing something, let us know.

Citing

preCICE is an academic project, developed at the Technical University of Munich and at the University of Stuttgart. If you use preCICE, please cite us.

If you are using deal.II, please also consider the information on the deal.II webpage

License

Please see the LICENSE file for details.

dealii-adapter's People

Contributors

davidscn avatar fsimonis avatar kyledavissa avatar makish avatar renefritze avatar shkodm avatar uekerman avatar vryy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dealii-adapter's Issues

Support Force data in addition to Stress data

Considering the new plans for the tutorials, the deal.II codes are different from other structure codes since they use Stress data for the coupling instead of Force data. In case of the linear model, it would be easy to integrate the Force in the adapter (though not fully consistent). The result looks the following way:
comparison

Since the linear model doesn't differentiate between deformed configuration and reference configuration, I just ignore these differences in the coupling data for the Forces, i.e., although I obtain the coupling data in deformed configuration, I sum it up in my linear system, which uses the reference configuration. For the Stress data, the difference is also neglected in terms of the vector orientation, but not in terms of the surface integrals. Hence, the main difference here is that we integrate the Stress data set in deal.II in the reference frame whereas we just add the integral contribution of the Force data calculated in the deformed frame (at least in OF).

In case of the perpendicular flap, the accuracy of the coupled system deteriorates apparently. However, it doesn't make sense to compare them: the linear model is for large deformations not valid and in case we have more compression of our elastic body instead of the elongation of the flap the accuracy between both approaches might be vice versa. For small deformations, the differences are only hardly noticeable so that the approach seems sufficiently. Still, I would not recommend to use the Force data.

For the nonlinear solver, I have not yet an idea how to support both data sets without larger changes while preserving a consistent formulation of the problem. Maybe it would be sufficient to support just the linear model with the new tutorials and request some user changes for the nonlinear case. If we provide comprehensive instructions for necessary changes, the approach might even better help users to learn about the coupling and coupled codes.

Add a `GridIn` interface to the adapter

Right now, the grid generation is hard-coded in the solver codes, with some refinement parameters in the parameter file

Solid<dim, NumberType>::make_grid()

However, this is quite intrusive for people, who are not familiar with deal.II and the code. deal.II has the GridIn class in order to read mesh files from the filesystem and we should try to make it compatible with our solver codes. This will only work for hexahedral meshes so far.

In a best case scenario, we could create a separate class, which can be used in both solver codes. As an alternative, one could directly replace the make_grid code by some GridIn function. Important will be the setting of the boundary IDs in order to apply proper boundary conditions. If setting the boundary IDs through the mesh file fails, we can add additional parameters in the parameter file in order to handle this parametrized.

As a first step, we could try to run one of our tutorial cases with an external mesh, e.g., the flap.

Replace global vector for interface values by boundary vector

The coupling values obtained from preCICE are currently stored in a global DoF vector, although we just have an entry for all coupling DoFs, i.e. most of the entries are wastefully allocated but unused. The reason was initially the utilization of get_function_values() during the assembly operation, which can easily return local DoF values from a global solution vector. I just stumbled across another variant of this function, which allows to specify the indices of the respective vector from which we want to get the local function values:
https://www.dealii.org/developer/doxygen/deal.II/classFEValuesBase.html#a378b552c1b8ca9f23f89677910e7a5cd

The other variant might be a much more efficient solution, but the changes require some changes in the system assembly and the Adapter class.

Dimension mismatch in 2D for FV based solver

In 2D simulations, FV solver have actually a 3D grid (one cell) and just the calculations are treated as quasi 2D, which means the out-of-plane component is neglected. But data (zeros) for the irrelevant component is still existing in the solvers and hence, the adapters are designed to handle 3D data sets. Also, precice gets 3D as parameter in the configuration file.
In FE solvers, the 2D simulation has a real 2D grid and therefore, no 3D data (coordinates and coupling data) is available.
There are until now two options, to get rid of this problem:

  1. A 3D grid is also created in the FE solver and the out-of-plane motion is constrained (zero displacement). Disadvantage: The whole system becomes twice as big in case of linear elements. If higher order elements are selected, it becomes even bigger.
  2. We ask with precice.getDimensions() for the precice dimension and design the adapter in such a way, that unavailable data is filled with zeros. Then, deal.ii calculates in 2D without telling precice.

Solution 1 can maybe used for first testing. For later, option 2 should be the way to go I guess

Non-linear solver does not compile

In the latest state of develop (as well as of master), the non-linear solver does not compile, reporting:

$ make 
Scanning dependencies of target nonlinear_elasticity
[ 50%] Building CXX object CMakeFiles/nonlinear_elasticity.dir/nonlinear_elasticity.cc.o
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc: In member function ‘void Nonlinear_Elasticity::Solid<dim, NumberType>::system_setup()’:
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:624:34: error: missing template arguments before ‘(’ token
     state_variables = std::vector({&total_displacement,
                                  ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc: In member function ‘void Nonlinear_Elasticity::Solid<dim, NumberType>::make_constraints(const int&)’:
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1359:50: error: ‘ZeroFunction’ was not declared in this scope
                                                  ZeroFunction<dim>(
                                                  ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1359:50: note: suggested alternative:
In file included from /home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1:0:
/usr/local/include/deal.II/base/function.h:510:9: note:   ‘dealii::Functions::ZeroFunction’
   class ZeroFunction : public ConstantFunction<dim, RangeNumberType>
         ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1366:50: error: ‘ZeroFunction’ was not declared in this scope
                                                  ZeroFunction<dim>(
                                                  ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1366:50: note: suggested alternative:
In file included from /home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1:0:
/usr/local/include/deal.II/base/function.h:510:9: note:   ‘dealii::Functions::ZeroFunction’
   class ZeroFunction : public ConstantFunction<dim, RangeNumberType>
         ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1383:13: error: ‘ZeroFunction’ was not declared in this scope
             ZeroFunction<dim>(n_components),
             ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1383:13: note: suggested alternative:
In file included from /home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1:0:
/usr/local/include/deal.II/base/function.h:510:9: note:   ‘dealii::Functions::ZeroFunction’
   class ZeroFunction : public ConstantFunction<dim, RangeNumberType>
         ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1390:13: error: ‘ZeroFunction’ was not declared in this scope
             ZeroFunction<dim>(n_components),
             ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1390:13: note: suggested alternative:
In file included from /home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1:0:
/usr/local/include/deal.II/base/function.h:510:9: note:   ‘dealii::Functions::ZeroFunction’
   class ZeroFunction : public ConstantFunction<dim, RangeNumberType>
         ^
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc: In instantiation of ‘void Nonlinear_Elasticity::Solid<dim, NumberType>::solve_nonlinear_timestep(dealii::BlockVector<double>&) [with int dim = 2; NumberType = double]’:
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:395:33:   required from ‘void Nonlinear_Elasticity::Solid<dim, NumberType>::run() [with int dim = 2; NumberType = double]’
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:1522:17:   required from here
/home/makish/github/dealii-adapter/nonlinear_elasticity/nonlinear_elasticity.cc:715:59: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
                error_residual_norm.u <= parameters.tol_f) ||
                                                           ^
CMakeFiles/nonlinear_elasticity.dir/build.make:62: recipe for target 'CMakeFiles/nonlinear_elasticity.dir/nonlinear_elasticity.cc.o' failed
make[2]: *** [CMakeFiles/nonlinear_elasticity.dir/nonlinear_elasticity.cc.o] Error 1
CMakeFiles/Makefile2:264: recipe for target 'CMakeFiles/nonlinear_elasticity.dir/all' failed
make[1]: *** [CMakeFiles/nonlinear_elasticity.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

I am using deal.II 9.2 and GCC 5.5.0.

I will happily close this if it is only on my side and my ancient compiler.

Automate dimension choice

We currently have two variants of the adapter: 2D (default) and 3D (more of an extra that we can easily support). The user currently needs to choose the one or the other at runtime, leading sometimes to confusion or to additional steps for switching between variants (mostly for us).

As discussed in #27, it would be nice to automate this (but not high priority).

Add inertial forces to solid solver

The solver is currently constructed to solve static elasticity problems. The FSI problem requires the consideration of dynamic effects. Therefore, we need to add inertial force terms in the solver.
We need roughly the following steps:

  • add time class for time stepping
  • add data structure to store time dependent values
  • build the mass matrix and add it to the equations
  • setup test case

Compile error: missing semicolon

I encountered a simple compile error while building the adapter due to a missing semicolon in the following lines of the source code:

  • File: elasticity.cc

    • Line: 99
    • Error: Expected ;
  • File: nonlinear_elasticity.cc

    • Line: 274
    • Error: Expected ;

Solution: Adding a semicolon at the end of the mentioned lines resolved the issue for me.

Environment Information:

  • Ubuntu version: 20.04.1
  • C++ version: 9.4.0

Missing error message for mixing a 2D solver with a 3D case

With deal.II 9.2, the latest state of the deal.II adapter and OpenFOAM 5 (and also v1912), I get the following error in the (3D) solid side very early in the simulation:

$ ./runSolid -linear
---[precice]  This is preCICE version 2.0.2
---[precice]  Revision info: v2.0.2
---[precice]  Configuring preCICE with configuration: "precice-config.xml"
Triangulation:
	 Number of active cells: 54
	 Polynomial degree: 2
	 Number of degrees of freedom: 518
	 Output written to solution-0.vtk 

	 Number of coupling nodes:     79
---[precice]  Setting up master communication to coupling partner/s
---[precice]  Masters are connected
---[precice]  Setting up preliminary slaves communication to coupling partner/s
---[precice]  Receive global mesh Fluid-Mesh-Centers
---[precice]  Receive global mesh Fluid-Mesh-Nodes
---[precice]  Prepare partition for mesh Solid_mesh
---[precice]  Gather mesh Solid_mesh
---[precice]  Send global mesh Solid_mesh
---[precice]  Setting up slaves communication to coupling partner/s
---[precice]  Slaves are connected
---[precice]  Compute read mapping from mesh "Fluid-Mesh-Centers" to mesh "Solid_mesh".
---[precice]  Using tree-based preallocation for matrix C
---[precice]  Using tree-based preallocation for matrix A
---[precice]  Mapping Stress consistent from Fluid-Mesh-Centers (ID 0) to Solid_mesh (ID 2) for dimension 0) with polynomial set to separate
---[precice]  Mapping Stress consistent from Fluid-Mesh-Centers (ID 0) to Solid_mesh (ID 2) for dimension 1) with polynomial set to separate
---[precice]  Mapping Stress consistent from Fluid-Mesh-Centers (ID 0) to Solid_mesh (ID 2) for dimension 2) with polynomial set to separate
---[precice]  it 1 of 50 | dt# 1 | t 0 of 5 | dt 0.01 | max dt 0.01 | ongoing yes | dt complete no | write-iteration-checkpoint | 
*** Error in `./linear_elasticity': free(): invalid pointer: 0x000000000218c4e0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f511e0307e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f511e03937a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f511e03d53c]
./linear_elasticity(_ZNSt8_Rb_treeIjSt4pairIKjN6dealii5PointILi2EdEEESt10_Select1stIS5_ESt4lessIjESaIS5_EE8_M_eraseEPSt13_Rb_tree_nodeIS5_E+0x269)[0x442be9]
./linear_elasticity(_ZNSt8_Rb_treeIjSt4pairIKjN6dealii5PointILi2EdEEESt10_Select1stIS5_ESt4lessIjESaIS5_EE8_M_eraseEPSt13_Rb_tree_nodeIS5_E+0xb2)[0x442a32]
./linear_elasticity(_ZN7Adapter7AdapterILi2EN6dealii6VectorIdEEN17Linear_Elasticity10Parameters13AllParametersEE10initializeERKNS1_10DoFHandlerILi2ELi2EEERKS3_RS3_+0x5b3)[0x445c83]
./linear_elasticity(_ZN17Linear_Elasticity14ElastoDynamicsILi2EE3runEv+0x7c)[0x45cdcc]
./linear_elasticity(main+0xd0)[0x4338e0]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f511dfd9830]
./linear_elasticity(_start+0x29)[0x433ba9]

Can anybody reproduce this?

The 2D case works for me.

Support dynamic time-step sizes

The implemented solvers only support constant time-step sizes. We added asserts to prevent misuse. The time-stepping schemes could theoretically handle dynamic time-step sizes, but within the solvers, we create initially dependent data structures once, such that a dynamic time-step size invalidates these data structures. Examples:

// Coefficients, which are needed for time dependencies
const double alpha_1 =
1. / (parameters.beta * std::pow(parameters.delta_t, 2));
const double alpha_2 = 1. / (parameters.beta * parameters.delta_t);
const double alpha_3 = (1 - (2 * parameters.beta)) / (2 * parameters.beta);
const double alpha_4 =
parameters.gamma / (parameters.beta * parameters.delta_t);
const double alpha_5 = 1 - (parameters.gamma / parameters.beta);
const double alpha_6 =
(1 - (parameters.gamma / (2 * parameters.beta))) * parameters.delta_t;

stepping_matrix *= time.get_delta_t() * time.get_delta_t() *
parameters.theta * parameters.theta;

Time integration scheme

One point to discuss is the choice of a suitable time integration scheme:
There are two frequently used schemes: The one-step-theta method and the Newmark's method.
The one-step-theta method has one parameter to adjust between Euler methods and a Crank-Nicolson scheme. Newmark's method has two parameters (beta, gamma) and thus more possible combinations to obtain certain properties. Therefore, Newmark's scheme takes slightly more effort in terms of computation and programming.

Add pullback operation for force vector

The solid mechanics are currently solved in spatial coordinates. The forces are obtained by the coupling participant and precice computes the mapping once at the beginning. This no problem for the mapping itself, since there is no relative motion at the interface and hence, the respective data of each vertex is assigned to the same data of the coupling partner.
But it might happen, that the fluid solver provides the force vector with respect to material coordinates (at the interface). In this case, a pullback operation from the "material" interface to the "spatial" FE grid needs to be performed in order to obtain proper forces for the boundary conditions.

A general idea is to add a boolean variable to the parameter file to allow an adaption of the solver according to the fluid solver. For the first tutorial case with the openfoam-adapter it needs to be figured out, how the data is provided.

Switch off precice

The adapter is currently only for coupled simulations designed. It is planned to add a "switch on /off" for the precice coupling depending on an input parameter. This would be very useful e.g. in order to test the performance of the solid solver or the simulation setup.
How could such a feature be implemented? I guess a simple straight forward way would be to wrap the necessary code in an if-statement. I opened up the issue to collect ideas before starting: Is there another preferable and/or commonly used strategy from a programmers perspective?

Provide OpenFOAM consistent output interval

As discussed, the time output is currently defined by using a fixed number of time steps. This differs from OpenFOAM.
@MakisH could you specify, what would be the best solution here/ how it is commonly defined in OpenFOAM?

Support subcycling

The adapter is able to capture implicit couplings. Some small changes in the reload and save functions need to be done, in order to additionally support subcycling, since the 'old' time dependent variables will hold data from the last, and not from the coupling timestep.

Extend to nonlinear solid mechanics

As described in the Solver Details, the current model uses a purely linear approach. However, this is for most of the real FSI applications not valid and could be improved by extending the linear model to a nonlinear model:

The most straight forward extension would be the application of the so-called St. Venant–Kirchhoff material, which relates the 2nd Piola–Kirchhoff stress tensor (S) linearly to the Green–Lagrange strain (E) measure. Hence, we would still have a linear elastic material model, but the Green-Lagrange strain depends nonlinear on the current displacements. This results in a geometrical nonlinear model, which -in contrast to the linear model- uses an objective strain measurement.

The weak formulation of this problem reads as follows:
equation

Where the elasticity tensor C is the same as in the linear case and F denotes the deformation gradient. To solve this equation, one could choose a (quasi) Newton-Raphson method. Therefore, the equation need to be discretized and linearized. Afterwards, a linear system needs to be solved in each Newton iteration.

Provide better error message, if deal.II version is too old

I tried installing the adapter after installing Deal.II using apt on my Ubuntu 20.04 system. By default Ubuntu 20.04 gives me Deal.II 9.1.0, but the adapter requires 9.2.0 as indicated here. Since installing via apt was recommended by the documentation of the adapter this situation confused me a bit.

What I tried

cmake . gave the following error

~/dealii-adapter/linear_elasticity$ cmake .
-- Build type: Release
CMake Error at CMakeLists.txt:39 (MESSAGE):


  *** Could not locate a (sufficiently recent) version of deal.II.  ***



  You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake

  or set an environment variable "DEAL_II_DIR" that contains this path.


-- Configuring incomplete, errors occurred!

Here, I was unsure whether my deal.II installation is found or not. I finally cloned the deal.II github repository and when trying to build an example I got the following error

~/dealii/examples/step-1$ cmake .
CMake Warning at CMakeLists.txt:26 (FIND_PACKAGE):
  Could not find a configuration file for package "deal.II" that is
  compatible with requested version "9.3.0".

  The following configuration files were considered but not accepted:

    /usr/share/cmake/deal.II/deal.IIConfig.cmake, version: 9.1.1



CMake Error at CMakeLists.txt:30 (MESSAGE):


  *** Could not locate a (sufficiently recent) version of deal.II.  ***



  You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake

  or set an environment variable "DEAL_II_DIR" that contains this path.


-- Configuring incomplete, errors occurred!

From my perspective this error message was very useful, since it told me that:

  1. my deal.II is found
  2. my deal.II version is too old

My Suggestion

Is it possible to add a similar error in the CMakeLists.txt of the adapter?

deal.II dynamic assert doesn't terminate coupled simulation

There are various options to raise an exception in deal.II, and they always use the Assert or AssertThrow mechansim. The Assert macro is a debug assert and uses the std::abort mechanism (see here) whereas the AssertThrow mechanism is used for dynamic error checking throws the exception normally. The abort assert mechanism works well, but the dynamic mechanism does not. The asserted participant terminates the calculation and preCICE prints:

---[precice]  Implicitly finalizing in destructor

but no message and no stacktrace is printed on the screen, the asserted participant hangs at this point (not terminated), and other participants keep waiting for response. That's in particular a problem if you run your cases on a cluster and you don't get any information about your failed simulation. Apart from that, the missing message and the missing stacktrace is a problem for user.
Hence, I guess there is some clash with preCICE internals. I don't really understand the behavior at the moment. I'm using deal.II 9.3.0-pre and precice2.1.1.

It's also worth noting that the Assertmechanism doesn't trigger the preCICE destructor as shown above. I think preCICE catches the usual throw somehow so it might be related to a preCICE change where we added the implicit finalization.

Maybe @fsimonis has an idea about this.

Discussion: useful deal.II adapter updates

Thinking about the upcoming adapter presentation during the workshop it might be worth to modernize/update some structures and capabilities of the current adapter state. I have a lot of ready-to-use code floating around which might be useful. However, it's a preCICE project, so what do others think about these features:

  • merge both solver in a single executable instead of two. Do not merge the codes itself, but rather bundle the codes together. In the long run, a base class implementation for the time loop might be useful as well
  • add a separate CaseBase interface and a derived class for each test case (i.e. mesh and BCs) in order to reduce the current duplication between both solvers
  • add a unit like GH test which tests each solver against a cpp solverdummy (for contribution)
  • add a functionality for reading and writing on quadrature points in addition to DoFs
  • add a functionality for writing data on equidistant meshes
  • add a functionality to automate the creation of an output directory for simulation data

InitializeData skipped in case no WriteInitialData is required

In our current implementation, the initializeData call is only reached in case WriteInitialData is required. However, in case another participants needs to initialize data and the dealii participant does not, the function call is skipped and preCICE complains:

---[precice] ERROR:  initializeData() needs to be called before advance if data has to be initialized.

This is probably a bug, but I would like to get some other opinions.

if (precice.isActionRequired(precice::constants::actionWriteInitialData()))
{
// store initial write_data for precice in write_data
format_deal_to_precice(deal_to_precice);
precice.writeBlockVectorData(write_data_id,
n_interface_nodes,
interface_nodes_ids.data(),
write_data.data());
precice.markActionFulfilled(
precice::constants::actionWriteInitialData());
precice.initializeData();
}

EDIT: Maybe something like actionReadInitialData would be useful.

Results for master (9.2.0) and 9.1.0 branch differ

I just did an experiment, where I ran Deal.II with a fake fluid solver that just provides a constant force. I can provide more details, if needed.

First I started with deal.II version 9.1.0 and the corresponding branch of the adapter (cac50c4) and got this result:

Fake-Deal II_9 1 0

I repeated the experiment with deal.II version 9.2.0 and the master branch of this repository (1d14846) and got this result:

Fake-Deal II_9 2 0

Both plots show the displacement of the tip in x and y direction. The amplitude of the oscillation differs a lot. One good candidate for the difference is #44.

Another note: The 9.2.0 version gives results that match very well with the same setup using FEniCS. Therefore, I am quite confident that the 9.2.0 version is correct and the 9.1.0 is not.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.